我如何实现Promise A+
栏目: JavaScript · 发布时间: 5年前
内容简介:初步实现Promise:1.实现三种状态:‘pending’, 'fulfilled', 'rejected'2.能够实现then方法两种回调函数的处理
new Promise((resolve, reject) => { //异步成功执行resolve,否则执行reject }).then((res) => { //resolve触发第一个回调函数执行 }, (err) => { //reject触发第二个回调函数执行 }).then(res => { //需要保证then方法返回的依然是promise //这样才能实现链式调用 }).catch(reason => { }); //等待所有的promise都成功执行then, //反之只要有一个失败就会执行catch Promise.all([promise1, ...]).then(); 复制代码
一、小试牛刀
初步实现Promise:
1.实现三种状态:‘pending’, 'fulfilled', 'rejected'
2.能够实现then方法两种回调函数的处理
//promise.js class Promise{ //传一个异步函数进来 constructor(excutorCallBack){ this.status = 'pending'; this.value = undefined; this.fulfillAry = []; this.rejectedAry = []; //=>执行Excutor let resolveFn = result => { if(this.status !== 'pending') return; let timer = setTimeout(() => { this.status = 'fulfilled'; this.value = result; this.fulfillAry.forEach(item => item(this.value)); }, 0); }; let rejectFn = reason => { if(this.status !== 'pending')return; let timer = setTimeout(() => { this.status = 'rejected'; this.value = reason; this.rejectedAry.forEach(item => item(this.value)) }) }; try{ //执行这个异步函数 excutorCallBack(resolveFn, rejectFn); } catch(err) { //=>有异常信息按照rejected状态处理 rejectFn(err); } } then(fulfilledCallBack, rejectedCallBack) { //resolve和reject函数其实一个作为微任务 //因此他们不是立即执行,而是等then调用完成后执行 this.fulfillAry.push(fulfilledCallBack); this.rejectedAry.push(rejectedCallBack); //一顿push过后他们被执行 } } module.exports = Promise; 复制代码
测试如下:
let Promise = require('./promise'); let p1 = new Promise((resolve, reject) => { setTimeout(() => { Math.random()<0.5?resolve(100):reject(-100); }, 1000) }).then(res => { console.log(res); }, err => { console.log(err); }) 复制代码
二、 完成链式效果
最大的难点在于链式调用的实现,具体来说就是then方法的实现。
//then传进两个函数 then(fulfilledCallBack, rejectedCallBack) { //保证两者为函数 typeof fulfilledCallBack !== 'function' ? fulfilledCallBack = result => result:null; typeof rejectedCallBack !== 'function' ? rejectedCallBack = reason => { throw new Error(reason instanceof Error? reason.message:reason); } : null //返回新的Promise对象,后面称它为“新Promise” return new Promise((resolve, reject) => { //注意这个this指向目前的Promise对象,而不是新的Promise //再强调一遍,很重要: //目前的Promise(不是这里return的新Promise)的resolve和reject函数其实一个作为微任务 //因此他们不是立即执行,而是等then调用完成后执行 this.fulfillAry.push(() => { try { //把then里面的方法拿过来执行 //执行的目的已经达到 let x = fulfilledCallBack(this.value); //下面执行之后的下一步,也就是记录执行的状态,决定新Promise如何表现 //如果返回值x是一个Promise对象,就执行then操作 //如果不是Promise,直接调用新Promise的resolve函数, //新Promise的fulfilAry现在为空,在新Promise的then操作后.新Promise的resolve执行 x instanceof Promise ? x.then(resolve, reject):resolve(x); }catch(err){ reject(err) } }); //以下同理 this.rejectedAry.push(() => { try { let x = this.rejectedCallBack(this.value); x instanceof Promise ? x.then(resolve, reject):resolve(x); }catch(err){ reject(err) } }) }) ; } 复制代码
测试用例:
let p1 = new Promise((resolve, reject) => { setTimeout(() => { Math.random()<0.5?resolve(100):reject(-100); }, 1000) }) let p2 = p1.then(result => { //执行then返回的是一个新的Promise return result + 100; }) let p3 = p2.then(result => { console.log(result); }, reason => { console.log(reason) }) 复制代码
简单画图来模拟一下链式调用的内部流程:
有了then方法,catch自然而然调用即可:
catch(rejectedCallBack) { return this.then(null, rejectedCallBack); } 复制代码
三、Promise.all()
接下来实现Promise.all()
//为类的静态方法,而不是在原型上 static all(promiseAry = []) { let index = 0, result = []; return new Promise((resolve, reject) => { for(let i = 0; i < promiseAry.length; i++){ promiseAry[i].then(val => { index++; result[i] = val; if( index === promiseAry.length){ resolve(result) } }, reject); } }) } 复制代码
完整代码
现在手写一个简陋但是功能较为完备的Promise就大功告成了。
class Promise{ constructor(excutorCallBack){ this.status = 'pending'; this.value = undefined; this.fulfillAry = []; this.rejectedAry = []; //=>执行Excutor let resolveFn = result => { if(this.status !== 'pending') return; let timer = setTimeout(() => { this.status = 'fulfilled'; this.value = result; this.fulfillAry.forEach(item => item(this.value)); }, 0); }; let rejectFn = reason => { if(this.status !== 'pending')return; let timer = setTimeout(() => { this.status = 'rejected'; this.value = reason; this.rejectedAry.forEach(item => item(this.value)) }) }; try{ excutorCallBack(resolveFn, rejectFn); } catch(err) { //=>有异常信息按照rejected状态处理 rejectFn(err); } } then(fulfilledCallBack, rejectedCallBack) { typeof fulfilledCallBack !== 'function' ? fulfilledCallBack = result => result:null; typeof rejectedCallBack !== 'function' ? rejectedCallBack = reason => { throw new Error(reason instanceof Error? reason.message:reason); } : null return new Promise((resolve, reject) => { this.fulfillAry.push(() => { try { let x = fulfilledCallBack(this.value); x instanceof Promise ? x.then(resolve, reject ):resolve(x); }catch(err){ reject(err) } }); this.rejectedAry.push(() => { try { let x = this.rejectedCallBack(this.value); x instanceof Promise ? x.then(resolve, reject):resolve(x); }catch(err){ reject(err) } }) }) ; } catch(rejectedCallBack) { return this.then(null, rejectedCallBack); } static all(promiseAry = []) { let index = 0, result = []; return new Promise((resolve, reject) => { for(let i = 0; i < promiseAry.length; i++){ promiseAry[i].then(val => { index++; result[i] = val; if( index === promiseAry.length){ resolve(result) } }, reject); } }) } } module.exports = Promise; 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- php如何实现session,自己实现session,laravel如何实现session
- AOP如何实现及实现原理
- webpack 实现 HMR 及其实现原理
- Docker实现原理之 - OverlayFS实现原理
- 为什么实现 .NET 的 ICollection 集合时需要实现 SyncRoot 属性?如何正确实现这个属性?
- 自己实现集合框架(十):顺序栈的实现
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python网络编程攻略
萨卡尔 (Dr.M.O.Faruque Sarker) / 安道 / 人民邮电出版社 / 2014-12-1 / 45.00元
开发TCP/IP网络客户端和服务器应用 管理本地设备的IPv4/IPv6网络接口 使用HTTP和HTTPS协议编写用途多、效率高的Web客户端 编写可使用常见电子邮件协议的电子邮件客户端 通过Telnet和SSH连接执行远程系统管理任务 使用Web服务与流行的网站交互 监控并分析重要的常见网络安全漏洞一起来看看 《Python网络编程攻略》 这本书的介绍吧!