异步编程的几种模式
回调和事件
Promise
Async,Wait
Promise
Promise 是 ES6 提供的原生类,简单的说就是一个容器,里面保存着某个异步执行的操作结果(也就是说未来才会获得的结果)。类似于Java 中的 Future 类。
三种状态:pending(进行中),fulfilled(成功, resolved),rejected(失败)
状态变化:
- pending => fulfilled
- pending => rejected
有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
缺点:
- 无法取消,一旦新建就会立即执行;
- 如果不设置回调函数,Promise 内部会抛出错误;
- 当出于 pending 状态时,无法得知目前进展到哪一个阶段;
示例 1:
let start=newDate().getTime();letlog=(msg)=> console.log(msg+" - "+(newDate().getTime()- start))log("mark 1");let p=newPromise((res, rej)=>{log("mark 2");res("mark 5");log("mark 3");})
p.then((value)=>log(value));
p.then((value)=>log(value));log("mark 4");
示例 2
console.log("mark 1");let p=newPromise((res, rej)=>{
console.log("mark 2");letout=()=>{
console.log("xxxx");res("vava");}setTimeout(()=>{res("mark 5")},2000,);
console.log("mark 3");})
p.then((value)=>console.log(value));
p.then((value)=>console.log(value));
console.log("mark 4");
说明:
- 从外部看来,Promise 的创建不会导致程序阻塞;
- 调用 then 方法,出入的回调函数会被延迟执行;
- then 方法可以重复调用;
- then(success, fail):then 方法可以接受两个回调函数作为参数,第一个回调函数在 Promise 对象的状态变为 resolved 时调用,第二个回调函数在 Promise 对象的状态转变为 rejected 时调用。
MyPromise
可以通过下面的自定义类,来模拟 Promise 的行为:
classMyPromise{constructor(callback){letres=(params)=>this.res(params);// 这里使用了类似拦截器或者代理的效果,对目标 res 进行包裹letrej=(params)=>this.rej(params);this.status=0;// pendingthis.actions=[];this.params=null;callback(res, rej);// 当创建 MyPromise 对象时,立即调用传入的回调方法;}// 实际的 res,rej 函数实例是通过 then 函数传进来的then(res, rej){if(this.status===0){// 如果处在 pending 状态,就将 res,rej 回调方法缓存起来,等有结果了再调this.actions.push([res, rej]);return;}if(this.status===1){res(this.params);return;}if(this.status===2){rej(this.params);}}res(params){this.params= params;this.status=1;// fullfiledthis.actions.forEach(action=> action[0](params));}rej(params){this.params= params;this.status=2;// rejectedthis.actions.forEach(action=> action[1](params));}}