Javascript进阶笔记
Promise
基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const promise = new Promise( (resolve,reject) => { if() { resolve(result); } else { reject(error); } } ); promise.then( (res) => { } ).catch( (error) => { } );
|
初始化Promise对象时需要传入一个函数,函数内部用来处理异步操作。该函数内置了两个参数resolve和reject。resolve则将padding状态变为fulfilled,进入下一个then。而reject则将状态变为reject,进入下一个catch。
被吃掉的错误
1 2 3 4 5 6 7 8 9 10 11 12 13
| const someAsyncThing = function() { return new Promise( (resolve,reject) => { resolve(x); } ); }; someAsyncThing().then(function() { console.log('everything is great'); }); setTimeout(() => { console.log(123) }, 2000);
|
Promise内的函数new出来的时候会立即执行,尽管Promise内的函数发生了错误,但是不会终止脚本的执行,会等到脚本结束时,错误信息随其他输出一并输出。因而最好使用catch方法捕获错误。
不能被吃掉的错误
1 2 3 4 5 6 7 8 9
| function p1(){ return new Promise((resolve,reject) => { x }); } p1().catch((e) => { console.log(e.message); });
|
对于Promise内部非异步语句,Promise都能吃掉,如果有catch方法的话能被catch方法捕获到,不过遇到以下情况的话:
1 2 3 4 5 6 7 8 9
| function p1(){ return new Promise((resolve,reject) => { setTimeout(() => {throw new Error('xxx')},2000); }); } p1().catch((e) => { console.log(e.message); });
|
这种情况将无法捕获,因此有延时函数在,此时延时函数的回调执行将跟Promise不在同一轮,轮到回调执行时,Promise已经运行完,此时的异常为Promise外的异常。
遇到这种情况的异常应该异步的回调函数内部使用try,catch捕获,然后catch内可以使用reject方法将错误抛给Promise的catch。
catch之后可以继续
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const someAsyncThing = function() { return new Promise( (resolve,reject) => { resolve(x); } ); }; someAsyncThing().catch( (e) => { console.log("error"); return "from-catch" } ).then( (str)=>{ console.log(str); } );
|
Promise.prototype.finally()
1 2 3 4
| promise .then(result => {···}) .catch(error => {···}) .finally(() => {···});
|
finally回调函数不接受任何参数,因此finally的执行与Promise的执行状态无关,一旦前面操作完成后,必定执行。
Promise.all()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| function p1(){ return new Promise((resolve) => { setTimeout(()=>{resolve(1)},5000); }); } function p2(){ return new Promise( (resolve) => { resolve(2) }); } function p3(){ return new Promise( (resolve) => { resolve(3) }); } const p = Promise.all([p1(),p2(),p3()]); p.then( ([r1,r2,r3]) => { console.log("success"+r1+r2+r3); } ).catch( (e) => { console.log(e.name+":"+e.message); } );
|
all方法,当数组内的Promise对象的状态都是fulfilled时,p的状态才是fulfilled。否则,当中有一个为reject时,p的状态将设置为reject,然后将第一被reject的实例传给catch,后面的实例虽然仍继续运行,但是尽管reject或者抛出异常也不会传给catch方法。
Promise.race()
1
| const p = Promise.race([p1, p2, p3]);
|
只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
将多个异步变为同步操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const p = new Promise( (resolve,reject) => { setTimeout(()=>{console.log("start");resolve();},1000); } ); p.then(() => { return new Promise( (resolve,reject) => { setTimeout(()=>{console.log("1");resolve();},4000); } ); }).then(() => { return new Promise( (resolve,reject) => { setTimeout(()=>{console.log("2");resolve();},1000); } ); });
|
以上将会将3个异步操作按同步的方式依次执行。此方法若没有业务需求,尽量少用。
async/await
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function asyncFunc() { return new Promise( (resolve,reject) => { setTimeout(()=>{resolve("result");},2000); } ); } async function exec(){ const result = await asyncFunc(); console.log(result); } exec();
|
async表示这里有异步操作,await表示需要等待后面异步操作结果的获取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function asyncFunc() { return new Promise( (resolve,reject) => { setTimeout(()=>{resolve("result");},2000); } ); } async function exec(){ const result = await asyncFunc(); return result; } exec().then((res)=>{ console.log(res); });
|
async函数返回一个Promise包装的对象,因此可以使用then进行后续操作。
函数节流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function throttle(func,duration) { var saveFunc = func; var timmer; var firstTime = true; return function() { var args = arguments; var _this = this; if (firstTime) { saveFunc.apply(_this,args); } if (timmer) return false; timer = setTimeout(function() { clearTimeout(time); timer = null; saveFunc(_this,args); },duration); } }
|
降低func函数的频率。func函数除了第一次执行以外,每次调用的有一定的间隔。
函数防抖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| function debounce(func,wait,immediate) { var timer,args,context,triggerTime,result; var later = function() { var last = new Date().getTime() - triggerTime; if(last<wait && last>=0) { timer = setTimeout(later,wait-last); } else { timer = null; if(!immediate) { result = func.apply(context,args); if(!timer) context = args = null; } } } return function() { context = this; args = arguments; triggerTime = new Date().getTime(); var callNow = immediate && !timer; if(!timer) timer = setTimeout(later,wait); if(callNow) { result = func.appply(context,args); context = args = null; } return result; }; }
|
函数防抖即在离最近触发要经过一段时间才能生效,否则每次触发都会重置计时器,重新算下一次生效时间。wait参数为规定的固定时间,immediate为true时表示前缘触发(生效条件成立时一触发就生效),为false为后缘触发(生效条件成立后经过固定时间才生效)。
每当调用函数内的闭包时,就会更新触发时间。later延时执行,每当到执行时间,就会检查是否固定时间内是否有过触发,如果有,就需要补时间(wait-last)。前缘触发的执行在闭包的apply中,后缘触发的执行在later函数中。
函数分时
分时函数可以将大量的dom操作或者性能耗费大的任务按时间分批执行。
1 2
| var x = setInterval(func,millisec); clearInterval(x);
|
分时函数需要setInterval和clearInterval来实现,setInterval函数会按周期性执行回调函数。而clearInterval函数则用来取消设定的Interval。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| var timeChunk = function(dataArray,func,count,duration) { var timer; var isRunning = false; var exec = function() { if(count<=0) count = 1; for (var i = 0; i < Math.min(count,dataArray.length); i++) { var data = dataArray.shift(); func(data); } } return function() { if (isRunning) return; isRunning = true; timer = setInterval(function() { if (dataArray.length == 0) { clearInterval(timer); isRunning = false; } exec(); },duration); } }
|
最后更新时间:
对本文内容有任何意见,建议,疑问etc,均可通过邮箱联系我,逗比博主尽最大努力回复O(∩_∩)O,如需转载(tan90°,不存在的(°Д°)),注明出处即可!