在学习如何写Promise之前,先要熟悉Promise的使用,然后一步一步去实现
【Promise的基本使用】:
1. Promise 是一个类 在执行这个类的时候需要传递一个执行器进去,执行器会立即执行
2. Promise中有三种状态,分别是:等待pending 成功fulfilled 失败rejected(状态一旦确定不可改变)
3. 执行器接收两个参数resolve(成功执行的方法)和reject(失败执行的方法)
4. Promise拥有then方法,方法内部需判断状态,接收了两个回调函数,如果成功调用成功的回调,如果失败调用失败的回调。then方法是被定义在原型对象中的
const promise = new Promise((resolve, reject) => {resolve('成功')// reject('失败')
})
promise.then(value => {console.log(value)
}, reason => {console.log(reason)
})
【实现步骤】:
【代码】:
// 4. 定义状态常量(成功fulfilled 失败rejected 等待pending),初始化为pending。
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'// 1 创建MyPromise类
class MyPromise {// 2 通过构造函数constructor,在执行这个类的时候需要传递一个执行器进去并立即调用constructor(executor) {// 13 Promise实现捕获错误try {executor(this.resolve, this.reject)} catch (e) {this.reject(e)}}status = PENDING// 6. MyPromise类中定义value和reason,用来储存执行器执行成功和失败的返回值value = nullreason = null// 9. 实现then方法多次调用添加多个处理函数 初始化回调为数组依次执行successCallback = []failCallback = []// 3. 定义resolve和reject(定义为箭头函数:避免直接调用时this指向全局window问题)resolve = value => {// 5. 完成resolve函数的状态改变(注意:需判断当前状态是否可以改变)// 判断当前状态是否可改变if(this.status !== PENDING) return// 改变当前状态this.status = FULFILLED// 保存返回值this.value = value// 执行成功回调while(this.successCallback.length) {this.successCallback.shift()(this.value)}}reject = reason => {// 5. 完成reject函数的状态改变(注意:需判断当前状态是否可以改变)// 判断当前状态是否可改变if(this.status !== PENDING) return// 改变当前状态this.status = REJECTED// 保存返回值this.reason = reason// 执行失败回调while(this.failCallback.length) {this.failCallback.shift()(this.reason)}}// 7. MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值;失败回调有一个参数 表示失败后的原因then(successCallback, failCallback) {// 14 将then方法的参数变为可选参数successCallback = successCallback ? successCallback : value => this.valuefailCallback = failCallback ? failCallback : reason => {throw this.reason}// 10. 实现then方法链式调用(写一个函数方法专门判断回调的结果是普通值还是promise,then方法返回的仍然是一个promise)let promise2 = new MyPromise((resolve, reject) => {// 判断当前状态 执行对应回调 异步情况下存储当前回调等待执行if(this.status === FULFILLED) {// 异步setTimeout(() => {// 13 then方法捕获错误try {// 异步获取到promise2let x = successCallback(this.value)resolvePromise(promise2, x, resolve, reject)} catch (e) {reject(e)}})} else if(this.status === REJECTED) {// 异步setTimeout(() => {// 13 then方法捕获错误try {// 异步获取到promise2let x = failCallback(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (e) {reject(e)}})} else {// 8. 处理异步逻辑(pending状态下在then中将回调存起来)this.successCallback.push(() => {try {let x = successCallback(this.value)resolvePromise(promise2, x, resolve, reject)} catch(e) {reject(e)}})this.failCallback.push(() => {try {let x = failCallback(this.reason)resolvePromise(promise2, x, resolve, reject)} catch(e) {reject(e)}})}})return promise2}// 17. finally方法 不管成功失败都会执行一次finally(callback) {return this.then(value => {return MyPromise.resolve(callback()).then(() => value)}, reason => {return MyPromise.reject(callback()).then(() => { throw reason })})}// 18. catchcatch(failCallback) {return this.then(undefined, failCallback)}// 15. Promise.allstatic all (array) {let result = []let indexreturn new Promise((resolve, reject) => {function addData(key, value) {result[key] = valueindex++if(index === array.length) {resolve(result)}}for(let i = 0; i < array.length; i++) {let current = array[i]if(current instanceof MyPromise) {current.then(value => addData(i, value), reason => reject(reason))} else {addData(i, array[i])}}})}// 16. Promise.resolve 返回一个promisestatic resolve(value) {if(value instanceof MyPromise) return valuereturn new MyPromise(resolve => resolve(value))}
}// 处理promise返回值各种类型情况(普通值,promise)
function resolvePromise(promise2, x, resolve, reject) {if(promise2 === x) {return reject(new TypeError('Chaining cycle detected for promise #'))}if(x instanceof MyPromise) {x.then(resolve, reject)} else {resolve(x)}
}
【对应验证代码】:
Document