系列文章
- Promise源码解密-PromisesA+标准
- Promise源码解密-同步版
- Promise源码解密-异步版
- Promise源码解密-then的链式调用
- Promise源码解密-catch/resolve/reject/race
创作不易 拒绝白嫖 点个赞呗
关注专栏 Promise源码解密,带你走进Promise的深处!!!
解决了啥
在同步版本中,我们在执行器中编写异步代码的情况下,
会导致先执行then,在执行异步的方法中的resolve或者reject。
所以我们就需要将then中接收到的方法转移到执行器中的异步方法中执行。
我们只需要将then接收到的方法,展示存起来,当调用到resolve/reject时,再执行then接收到的方法
代码
// 定义状态常量 const STATUS_PENDING = 'pending' const STATUS_FULFILLED = 'fulfilled' const STATUS_REJECTED = 'rejected' class MyPromise { // 接收一个 执行器 // new Promise的时候,执行器立即执行, // 执行的时候根据指定函数执行 // 并且程序报错的情况下 constructor(executor) { this.status = STATUS_PENDING this.value = undefined this.reason = undefined this.onFulfilledCallBacks = [] this.onRejectCallBacks = [] try { executor(this.resolve, this.reject) } catch (error) { // 报错的话直接将错误原因作为reason this.reject(error) } } // 这里为啥使用箭头函数而不是resolve(){} // 这是因为上面的executor调用的时候,resolve中的this其实是undefined // executor单独调用了resolve/reject 这时,这两个方法存在于执行是的环境,this不再指向实例 // 箭头函数内部的this总是指向定义时所在的对象 resolve = (value) => { // 判断状态是不是 if (this.status === STATUS_PENDING) { console.log('执行resolve') // 这里接收传进来的结果 this.value = value this.status = STATUS_FULFILLED // 如果有存放起来的then接收的函数,立即遍历执行,这样保证then方法还是最后调用 this.onFulfilledCallBacks.forEach((fn) => { fn() }) } } reject = (reason) => { if (this.status === STATUS_PENDING) { console.log('执行reject') // 这里接收传进来的错误的结果 this.reason = reason this.status = STATUS_REJECTED this.onRejectCallBacks.forEach(fn => { fn() }) } } then(onFulfilled, onReject) { console.log('执行then时的状态: ', this.status) if (this.status === STATUS_FULFILLED) { console.log("执行 onFulfilled") onFulfilled(this.value) } if (this.status === STATUS_REJECTED) { console.log("执行 onReject") onReject(this.reason) } // 如果状态是pending的话,暂时存放起来。 // 在异步情况下,回先执行then,所以状态是pending if (this.status === STATUS_PENDING) { this.onFulfilledCallBacks.push(() => onFulfilled(this.value)) this.onRejectCallBacks.push(() => onReject(this.reason)) } } } let t = new MyPromise((resolve, reject) => { // 指定执行哪个,resolve和reject最终只会执行一个 // console.log(a) // 执行console会报错,最终只会执行reject // // resolve("res") // reject('reject') setTimeout(() => { resolve('异步执行结束') }, 1000) }) t.then((res) => { console.log(res) }, (error) => { console.log(error) })
注意点
这里使用数组保存了then的回调函数
为啥是数组呢?
可能有多个then
//index.js promise.then(value => { console.log(value) }) promise.then(value => { console.log(value) }) promise.then(value => { console.log(value) })