手写Promise(1)

一、构建#
本次推文将会手写开发Promise实现,提升异步编程的能力。
首先声明定义类并声明Promise状态与值,有以下几个细节需要注意。
executor为执行者- 当执行者出现异常时触发拒绝状态
- 使用静态属性保存状态值
- 状态只能改变一次,所以在
resolve与reject添加条件判断 - 因为
resolve或rejected方法在executor中调用,作用域也是executor作用域,这会造成this指向window,现在我们使用的是class定义,this为undefined
案例代码测试:
二、THEN#
现在添加then方法来处理状态的改变,有以下几点说明
then可以有两个参数,即成功和错误时的回调函数then的函数参数都不是必须的,所以需要设置默认值为函数,用于处理当没有传递时情况- 当执行
then传递的函数发生异常时,统一交给onRejected来处理错误
1.基础构建#
案例代码测试(then方法代码放进MyPromise类中):
2.异步任务#
前面代码中的then方法可以正常执行,但代码产生的Promise并不是异步的,所以我们需要使用setTimeout来将onFulfilled与onRejected做为异步宏任务执行。
案例代码测试(Promise异步执行):
3.PENDING状态#
目前then方法无法处理promise为pending时的状态
所以为了处理上述情况,需要进行几点改动
在构造函数中添加callback来保存pending状态时的处理函数,当状态改变时循环调用。
constructor(executor){...this.callbacks = [];...}将then方法的回调函数添加到callback数组中,用于异步执行。
then(onFulfilled,onRejected){if(typeof onFulfilled != "function"){onFulfilled = value => value;}if(typeof onRejected != "function"){onRejected = value => value;}if(this.status == MyPromise.PENDING){this.callbacks.push({onFulfilled: value =>{try{onFulfilled(value);} catch(error){onRejected(error);}},onRejected: value =>{try{onRejected(value);} catch(error){onRejected(error);}}});}...}
resolve方法和reject方法中添加处理callback方法的代码。
resolve(value){if(this.status == MyPromise.PENDING){this.status = MyPromise.FULFILLED;this.value = value;this.callbacks.map(callback =>{callback.onFulfilled(value);});}}reject(value){if(this.status == MyPromise.PENDING){this.status = MyPromise.REJECTED;this.value = value;this.callbacks.map(callback =>{callback.onRejected(value);});}}
4.PENDING异步#
执行以下代码发现并不是异步操作,应该先输出 "我要先执行!" 然后是 "前端收割机!!!!"。
解决以上问题,只需要将resolve与reject执行通过setTimeout定义为异步任务。
三、链式操作#
Promise中的then是链式调用执行的,所以then也要返回Promise才能实现
- then的onReject函数是对前面Promise的rejected的处理
- 但该Promise返回状态要为fulfilled,所以在调用onRejected后改变当前promise为fulfilled状态
案例代码测试:
四、返回类型#
如果then返回的值为Promise,我们需要如何处理?所以我们需要判断分别处理返回值为Promise与普通值的情况。
- 基本实现
- 代码复用
现在发现pendding、fulfilled、rejected 状态的代码非常相似,所以可以提取出方法Parse来复用
- 返回约束
then的返回的promise不能是then相同的Promise,下面是原生Promise的示例将产生错误
解决上面的问题来完善代码,添加当前promise做为parse的第一个参数与函数结果比对
案例测试(现在进行测试也可以得到原生一样效果了)