记录promise的一次学习

101 阅读4分钟

ES6-阮一峰

手写promise

Promise的状态

状态的改变是不可逆的

enum PROMISE_STATE {
    PENDING = 'Pending',
    FULFILLED = 'Fulfilled',
    REJECTED = 'Rejected'
}

构造函数

  • new Promise 传入executor 执行器,executor 构造器两个函数分别对应resolve和reject
  • value 用于记录resolve的值
  • reason 用于记录reject的值
  • status 表示promise的状态

onFulfilledCallback/onRejectedCallback记录收集的callbacks

   class MyPromise {
    value: any = null;
    reason: any = null;
    status: StatusType = PROMISE_STATE.PENDING; 
    promiseName:string;
    onFulfilledCallback: any = [];
    onRejectedCallback: any = [];
    constructor(executor: (resolve: Fn, reject: Fn) => void) {
        // executor 执行器 传入后会立即执行
        this.promiseName = 'MyPromise'+ count++
        console.log('constructor',this.promiseName)
        try {
            executor(this.resolve.bind(this), this.reject.bind(this))
        } catch (error) {
            console.log('捕获执行器中的异常代码');
            this.reject(error)
        }
    }
   }

resolve

resolve主要用来将状态从pending->fulfilled,同时执行回调

 this.value = value;
        if (this.status === PROMISE_STATE.PENDING) {
            this.status = PROMISE_STATE.FULFILLED
            while (this.onFulfilledCallback.length) {
                this.onFulfilledCallback.shift()(this.value);
            }
  }

reject

reject主要用来将状态从pending->rejected,同时执行回调

  reject(reason: any) {
        this.value = reason;
        if (this.status === PROMISE_STATE.PENDING) {
            this.status = PROMISE_STATE.REJECTED
            while (this.onRejectedCallback.length) {
                this.onRejectedCallback.shift()(this.value);
            }
        }
    }

then

主要有两个作用

  • 返回promise对象用于链式调用
  • pending阶段收集函数(依赖),在状态改变的时候执行回调
  then(onFulfilled: Fn, onRejected?: Fn) {
        // console.log('promise then函数代码会立即执行,而函数则是在状态变化过后执行')
        // 没传置空
        if (returnType(onFulfilled) != '[object Function]') {
            onFulfilled = (value) => value
        }

        if (returnType(onRejected) != '[object Function]') {
            onRejected = (reason) => reason
        }
        let promise = new MyPromise((res, rej) => {

            if (this.status === PROMISE_STATE.FULFILLED) {
                // 使用微任务包裹onFulfilled的执行 这就是为什么then里面的函数是个微任务
                queueMicrotask(() => {
                    // 捕获then执行时候的异常
                    try {
                        // 获取then一个函数的返回值 作为下一个promise的函数的res值
                        // console.log(onFulfilled, 'onFulfilled', this.value)
                        const result = onFulfilled(this.value);
                        resolvePromise(promise, result, res, rej)
                    } catch (error) {
                        rej(error);
                    }
                })

            } else if (this.status === PROMISE_STATE.REJECTED) {
                queueMicrotask(() => {
                    try {
                        // 获取then一个函数的返回值 作为下一个promise的函数的res值
                        const result = onRejected!(this.value);
                        rejectPromise(promise, result, res, rej)
                    } catch (error) {
                        rej(error);
                    }

                })
            } else if (this.status === PROMISE_STATE.PENDING) {
                this.onFulfilledCallback.push(() => {
                    // // ==== 新增 ====
                    queueMicrotask(() => {
                        try {
                            // 获取成功回调函数的执行结果
                            const x = onFulfilled(this.value);
                            resolvePromise(promise, x, res, rej)
                        } catch (error) {
                            rej(error)
                        }
                    })
                });
                this.onRejectedCallback.push(() => {
                    queueMicrotask(() => {
                        try {
                            const x = onRejected!(this.value);
                            rejectPromise(promise, x, res, rej)
                        } catch (error) {
                            rej(error)
                        }
                    })
                });
            }
        })
        return promise;
    }

Demo1

       new MyPromise((res,rej)=>{
            setTimeout(() => {
                res('1111')
                console.log('promise1')
            }, 1000);
        }).then((res)=>{
           console.log('promise2')
            return 2222+res
        }).then((res)=>{
            console.log('promise3')
            console.log(res)
        })

分析:

promise1的状态改变之后执行收集的回调函数,得到回调函数执行结果再次resolve 从而改变了promise2的状态,promise2状态改变执行回调

promise1.jpg

Demo2

        new MyPromise((res,rej)=>{
            setTimeout(() => {
                console.log('promise1')
                res('1111')
            }, 1000);
        }).then((res)=>MyPromise.resolve('2222'))
          .then((res)=>{console.log(3333)})
          .then((err)=>{ console.log('4444')})

promise2.jpg

分析:

promise1的状态改变之后执行收集的回调函数,执行到MyPromise.resolve创建一个fulfilled状态promise5对象,得到回调返回结果发现一个promise对象,对promise对象进行then调用,此时创建promise6,执行完毕之后promise2状态改变,执行回调打印3333,然后resolve(undefined),从而promise3状态改变打印4444,接着继续resolve(undefined)用于后续的链式调用

static resolve

返回一个fuifulled状态的promise对象

  static resolve(val: any) {
        return new MyPromise((resolve, reject) => {
            if (val instanceof MyPromise) {
                val.then(resolve, reject)
            } else {
                resolve(val)
            }
        })
 }

static reject

返回一个rejected状态的promise对象

 static reject(reason: any) {
        return new MyPromise((resolve, reject) => {
            if (reason instanceof MyPromise) {
                reason.then(resolve, reject)
            } else {
                reject(reason)
            }
        })
    }

all

所有的promise都执行完毕了 才执行resolve,其中一个失败了就reject,当然也可以对promiseList进行一层catch,可用于并行多个请求 同都成功了再执行后续的操作

 static all(promiseList: any) {
        return new MyPromise((resolve, reject) => {
            if (!isAllPromise(promiseList)) {
                console.log('传递进来的列表中存在不是promise对象的');
                reject([])
            }
            const values: any = [];
            // 所有的promise都成功了 resolve 一个失败就reject
            promiseList.forEach((promise: any) => {
                promise.then((res: any) => {
                    values.push(res)
                    if (values.length == promiseList.length) {
                        resolve(values)
                    }
                }, (reason: any) => {
                    reject(reason)
                })
            });
        })

race

race意为赛跑 即一个promise状态fulfilled了 就resolve 可以用于请求多个服务器的同一个资源,那个优先返回就使用哪个

 static race(promiseList: any) {
        return new MyPromise((resolve, reject) => {
            if (!isAllPromise(promiseList)) {
                console.log('传递进来的列表中存在不是promise对象的');
                reject([])
            }
            // 哪一个promise先执行完就resolve
            promiseList.forEach((promise: any) => {
                promise.then((res: any) => {
                    resolve(res)
                }, (reason: any) => {
                    reject(reason)
                })
            });
        })
    }

allsettled

即不管promise的状态如何 执行完毕就resolve

static allSettled(promiseList: any) {
        return new MyPromise((resolve, reject) => {
            if (!isAllPromise(promiseList)) {
                console.log('传递进来的列表中存在不是promise对象的');
                reject([])
            }
            const values: any = [];
            promiseList.forEach((promise: any) => {
                promise.then((res: any) => {
                    values.push({
                        value: res,
                        status: 'Fulfilled'
                    })
                   
                }, (reason: any) => {
                    values.push({
                        status: 'Rejected',
                        value: reason
                    })
                }).finally(()=>{
                    if (values.length == promiseList.length) {
                        resolve(values)
                    }
                })
            });
        })
    }

any

一个promise成功了就resolve,全部失败了就reject

    static any(promiseList: any) {
        return new MyPromise((resolve, reject) => {
            if (!isAllPromise(promiseList)) {
                console.log('传递进来的列表中存在不是promise对象的');
                reject([])
            }
            const values: any = [];
            // 哪一个promise先执行完就resolve
            promiseList.forEach((promise: any) => {
                promise.then((res: any) => {
                    resolve(res)
                }, (reason: any) => {
                    values.push({
                        status: 'Rejected',
                        value: reason
                    })
                    if (values.length === promiseList.length) {
                        reject(values)
                    }
                })
            });
        })
    }

finally

不管promise的状态如何, 都会执行finally方法指定的callback

 finally(callBack: Fn) {
        return this.then(
            () => MyPromise.resolve(callBack()).then(value => value),
            () => MyPromise.resolve(callBack()).then((reason) => { throw reason }),
        );
    }

catch

捕获promise reject的情况 实现其实就是变相的调用then,等价于多写了一个then 且传递了第二个参数

    catch(onRejected: Fn) {
        return this.then(() => { }, onRejected)
    }