前言
上一章中已经讲完了promise最基本实现的原理,本章将在其基础上进行进一步的扩展,以满足更多的使用场景,源码在文章最后哦。
上一章链接:https://blog.csdn.net/weixin_42344533/article/details/117608576?spm=1001.2014.3001.5501
下一章链接:https://blog.csdn.net/weixin_42344533/article/details/117624450
过程
1、在上一个版本的promise实现中,虽然可以实现基本的功能,但是也存在着一个bug:如果resolve被包裹在setTimeout中执行,则结果会导致没有结果输出,如下图:
2、所以本章接下来讲解的为promise手动基本实现版本2,效果图如下:
3、版本1出现的bug主要原因,是promise对象在实例化过程中,由于外部执行函数resolve被包裹在setTimeout中,没有立即执行,造成实例化对象一直为pending状态,导致的结果就是执行then方法的时候,没有进入分支处理,最终也就没有任何输出。
所以版本2的实现,我们加入了订阅-发布的模式,所以在对象中引入了两个订阅数组,用于存储异步执行的事件:
4、then方法也需要做一点小小的修改:原理就是对象状态如果还是pending的时候,就可以认为外部resolve方法还没执行,就需要把当前事件推送到订阅数组中存储起来。
5、then方法把事件推送到订阅队列中后,需要真正执行的时候再去遍历订阅数组进行执行,所以也需要对init方法进行小小的改动。
总结
版本2在版本1的基础上,引入了订阅-发布的模式,通过订阅数组存储尚未发布(执行)的事件,然后在真正执行的时候去执行。
实现源码myPromise_v2.js:
const RESOLVE = 'resolved'
const REJECT = 'rejected'
const PENDING = 'pending'
function selfPromise(exe) {
this.status = PENDING
this.result = undefined
this.reason = undefined
this.resolveAsyList = []
this.rejectAsyList = []
this.init = (exe) => {
const resolve = (result) => {
if (this.status === PENDING) {
this.result = result
this.status = RESOLVE
this.resolveAsyList.map(resolveAsy => {
resolveAsy()
})
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.reason = reason
this.status = REJECT
this.rejectAsyList.map(rejectAsy => {
rejectAsy()
})
}
}
exe(resolve, reject)
}
this.init(exe)
this.then = (onResolve, onReject) => {
if (this.status === RESOLVE) {
setTimeout(() => {
onResolve(this.result)
}, 0)
}
if (this.status === REJECT) {
setTimeout(() => {
onReject(this.reason)
}, 0)
}
if (this.status === PENDING) {
this.resolveAsyList.push(() => {
onResolve(this.result)
})
this.rejectAsyList.push(() => {
onReject(this.reason)
})
}
}
}
module.exports = selfPromise
测试案例test.js:
const myPromise = require('./myPromise_v2')
var test = new myPromise((resolve,reject)=>{
setTimeout(()=>{
resolve("这是手动实现的promise")
},1000)
})
test.then(res=>{
console.log(res)
})
console.log("同步代码")
下一章将在版本2的基础上实现promise对象的链式调用
https://blog.csdn.net/weixin_42344533/article/details/117624450