我们手写一个Promise/A+规范,然后安装测试脚本,以求通过这个规范。 //Promise/A+源代码// new Promise时,需要传递一个executor执行器,执行器立即执行// executor接受两个参数,分别是resolve和
我们手写一个Promise/A+规范,然后安装测试脚本,以求通过这个规范。
//Promise/A+源代码 // new Promise时,需要传递一个executor执行器,执行器立即执行 // executor接受两个参数,分别是resolve和reject // promise只能从pending到rejected,或者从pending到fulfilled // promise的状态一旦确认,就不会再改变 // promise有then方法,then接受两个参数,分别是promise成功的回调onFulfilled // 和promise失败的回调 onRejected // 如果调用then时,promise已经成功,则执行onFulfilled,并将promise值作为参数传递进去 // 如果promise已经失败,那么执行onRejected并把promise失败的原因作为参数传递进去 // 如果promise状态是pending,需要将onFulfilled和onRejected函数存放起来,等待状态确定后,再一次将对应的函数执行(发布) // then的参数onFulfilled和onRejected可以缺省 // promise可以then多次,promise的then方法返回一个promise // 如果then返回的是一个结果,那么就把这个结果作为参数,传递给下一个then的成功的回调onFulfilled // 如果then中抛出了异常,那么就会把这个异常作为参数,传递给下一个失败的回调 onRejected // 如果then返回的是一个promise,那么需要等这个promise,那么会等这个promise执行完,promise如果成功 // 就走下一个then的成功,如果失败,就走下一个then的失败 //pending状态,可以认为是一种中间状态 const PENDING = 'pending'; // fullfilled完成状态,可以认为是成功回调了的状态 const FULFILLED = 'fullfilled'; // reject即为拒绝状态,即失败的状态 const REJECTED = 'reject'; // executor是一个执行器 function Promise(executor){ let self = this; self.status = PENDING; self.onFulfilled = [];//成功的回调 self.onRejected = [];//失败的回调 // PromiseA+ 2.1 function resolve(value){ if(self.status === PENDING){ self.status = FULFILLED; self.value = value; self.onFulfilled.forEach(fn=>fn());//PromiseA+ 2.2.6.1 } } function reject(reason){ if(self.status===PENDING){ self.status = REJECTED; self.reason = reason; self.onRejected.forEach(fn=>fn());//PromiseA+ 2.2.6.2 } } try{ executor(resolve,reject) }catch(e){ reject(e) } } // then必须返回一个promise Promise.prototype.then = function(onFulfilled,onRejected){ // PromiseA+ 2.2.1/PromiseA+ 2.2.5/PromiseA+ 2.2.7.3/PromiseA+2.2.7.4 onFulfilled = typeof onFulfilled ==='function'?onFulfilled:value =>value; onRejected = typeof onRejected === 'function'?onRejected:reason=>{throw reason}; let self = this; //PromiseA+ 2.2.7 let Promise2 = new Promise((resolve,reject)=>{ if(self.status===FULFILLED){ //PromiseA+2.2.2 // Promise A+2.2.4----setTimeout setTimeout(()=>{ try{ let x = onFulfilled(self.value); resolvePromise(promise2,x,resolve,reject); }catch(e){ //PromiseA+2.2.7.2 reject(e) } }); }else if(self.status === REJECTED){ // PromiseA+ 2.2.3 setTimeout(()=>{ try{ let x = onRejected(self.reason); resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); } }) }else if(self.status===PENDING){ self.onFulfilled.push(()=>{ setTimeout(()=>{ try{ let x = onFulfilled(self.value); resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); } }); }); } }); return promise2; } function resolvePromise(promise2,x,resolve,reject){ let self = this; //PromiseA+ 2.3.1 if(promise2===x){ reject(new TypeError('changing cycle')); } if(x && typeof x ==="object"|| typeof x ==='function'){ let used;//PromiseA+ 2.3.3.3.3//只能调用一次 try{ let then = x.then; if(typeof then === 'function'){ //PromiseA+2.3.3 then.call(x,(y)=>{ // PromiseA+ 2.3.3.1 if(used)return; used = true; resolvePromise(promise2,y,resolve,reject); },(r)=>{ //PromiseA+2.3.3.2 if(used)return; used = true; reject(r) }); }else{ //PromiseA+ 2.3.3.4 if(used)return; used = true; reject(x); } }catch(e){ //PromiseA+ 2.3.3.2 if(used)return; used = true; reject(e); } }else{ //PromiseA+ 2.3.3.4 resolve(x); } } module.exports = Promise;
我们可以用专门的测试脚本测试所编写的代码是否符合PromiseA+的规范。
在上面的promise实现的代码中,增加一下代码
Promise.defer = Promise.deferred = function(){ let dfd = {}; dfd.promise = new Promise((resolve,reject)=>{ dfd.resolve = resolve; dfd.reject = reject; }); return dfd; }
安装测试脚本
npm install -g promises-aplus-tests
如果当前的promise源码的文件名为promise.js
那么在对应的目录执行以下命令:
promises-aplus-tests promise.js
promises-aplus-tests中共有872条测试用例。以上代码,可以完美通过所有用例。
本文借鉴自:https://blog.csdn.net/liuyan19891230/article/details/88385973
这篇博客是ES6的写法:https://blog.csdn.net/weixin_41436338/article/details/79806033 有空就多学多看源码,你看那么多人那么牛逼啊