手写Promise
https://zhuanlan.zhihu.com/p/144058361 完整版(含链式调用)
class promise{ constructor(fn){ //初始pending状态 this.status = 'pending'; //成功fulfilled状态,保存value值 this.value = undefined; //拒绝rejected状态,保存reason值 this.reason = undefined; //支持异步,使用数组而不是单一变量防止多次then调用覆盖之前的回调函数 this.onFulfilled = [];//成功的回调 this.onRejected = []; //失败的回调 let resolve = value => { if(this.status == 'pending'){ this.status = 'fulfilled'; this.value = value; //成功异步执行在此调用 this.onFulfilled.forEach(fn=>fn(value)); } }; let reject = reason => { if(this.status == 'pending'){ this.status = 'rejected'; this.reason = reason; //失败异步执行在此调用 this.onRejected.forEach(fn => fn(reason)); } } try{ fn(resolve,reject); }catch(e){ reject(e); } } //onFulfilled,onRejected都是可选参数,如果不是函数则需要忽略 then(onFulfilled,onRejected){ if (this.status == 'fulfilled'){ typeof onFulfilled === 'function' && onFulfilled(this.value); } if (this.status == 'rejected') { typeof onRejected === 'function' && onRejected(this.reason); } // 异步状态来不及改变,如果还是pending则将回调先存储而不是立即调用 if (this.status === 'pending') { typeof onFulfilled === 'function' && this.onFulfilled.push(onFulfilled); typeof onRejected === 'function' && this.onRejected.push(onRejected); } } catch(onRejected){ if (this.status == 'rejected') { typeof onRejected === 'function' && onRejected(this.reason); } if (this.status === 'pending') { typeof onRejected === 'function' && this.onRejected.push(onRejected); } } //手写简易promise.all //要想使用类.方法调用需要定义为静态方法 static all(promises){ //没写如果没传入promise,只是做了抛出异常,实际上要转换为promise对象 if (!Array.isArray(promises)) { throw new Error('promises must be an Array') } return new promise(function (res, rej) { let length = promises.length; let result = []; for (let i = 0; i < length; i++) { //由于定义的这个类resolve方法没有返回值用的是原生Promise Promise.resolve(promises[i]).then(function (value) { result[i] = value; if (i == length-1) { return res(result); } }, function (reason) { return rej(reason); }) } }) } //手写简易promise.race static race(promises){ if (!Array.isArray(promises)) { throw new Error('promises must be an Array') } return new promise(function(res,rej){ promises.forEach(p=>{ p.then(function(value){ return res(value); },function(reason){ return rej(reason); }) }) }) } }