阅读 102

学习笔记:promise

promise是什么?

Promise 是一个对象,用于表示一个异步操作的最终完成 (或失败)及其结果值。

const promise = new Promise((resolve, reject) => {
   resolve('success')
   reject('err')
})

promise.then(value => {
  console.log('resolve', value)
}, reason => {
  console.log('reject', reason)
})

复制代码

如何实现一个promise?

一、声明一个class类

class MyPromise {
    
 }
 //function MyPromise(executor){
 //    es5构造函数
 //}
复制代码

二、定义promise的三种状态

1、pending: 初始状态(可转变成fulfilled或rejected)。
2、fulfilled: 完成。(最终态,不可改)
3、rejected: 失败。(最终态,不可改)

// 定义三个常量表示三个状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
复制代码

三、初始化promise的状态

class MyPromise {
    constructor() {
        // 初始状态为pending
        this.status = PENDING;//状态
        this.value = null;//成功的值
        this.reason = null;//失败的值
    }
 }
复制代码

四. resolve 和 reject 方法

1. 这两个方法是要更改status的, 从pending改到fulfilled/rejected.
2. 两个函数的入参分别是value 和 reason.
复制代码
resolve(value) {
    if (this.status === PENDING) {
       //这层判断是因为fulfilled状态只可以由pending状态改变而来
        this.status = FULFILLED;
        this.value = value;
    }
}
reject(reason) {
    if (this.status === PENDING) {
    //同理这层判断是因为rejected状态只可以由pending状态改变而来
        this.status = REJECTED;
        this.reason = reason;
    }
}
复制代码

五. 实例化promise时的入参处理

1.入参是一个函数, 接收resolve和reject两个参数.
2.初始化promise的时候就要同步执行这个函数, 并且有任何报错都要通过reject抛出去
复制代码
class MyPromise {
    constructor(fn) {
        // 初始状态为pending
        this.status = PENDING;//状态
        this.value = null;//成功的值
        this.reason = null;//失败的值
        try {
            fn(this.resolve.bind(this), this.reject.bind(this));
        } catch (e) {
            this.reject(e);
        }
    }

    resolve(value) {
        if (this.status === PENDING) {
           //这层判断是因为fulfilled状态只可以由pending状态改变而来
            this.status = FULFILLED;
            this.value = value;
        }
    }

    reject(reason) {
        if (this.status === PENDING) {
            //同理这层判断是因为rejected状态只可以由pending状态改变而来
            this.status = REJECTED;
            this.reason = reason;
        }
    }
 }
复制代码

六. then方法

1. then接收两个参数, onFulfilled 和 onRejected
2. 检查并处理参数, 如果参数不是function就忽略(原样返回value或者reason)
复制代码
class MyPromise {
    constructor(fn) {
        // 初始状态为pending
        this.status = PENDING;//状态
        this.value = null;//成功的值
        this.reason = null;//失败的值
        try {
            fn(this.resolve.bind(this), this.reject.bind(this));
        } catch (e) {
            this.reject(e);
        }
    }

    resolve(value) {
        if (this.status === PENDING) {
           //这层判断是因为fulfilled状态只可以由pending状态改变而来
            this.status = FULFILLED;
            this.value = value;
        }
    }

    reject(reason) {
        if (this.status === PENDING) {
            //同理这层判断是因为rejected状态只可以由pending状态改变而来
            this.status = REJECTED;
            this.reason = reason;
        }
    }
    
    then(onFulfilled, onRejected) {
        const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value) => value
        const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) => {
            throw reason
        };
    }
    
    //检验是否为function
    isFunction(param) {
        return typeof param === 'function';
    }
 }
复制代码
3. 根据当前promise的状态, 调用不同的函数
复制代码
class MyPromise {
    .....
    //这时候then函数被调用会瞬间就会执行switch判断,那这时候如果status可能还没变成fulfilled或者rejected,很有可能还是pending
    then(onFulfilled, onRejected) {
        const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value) => value
        const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) => {
            throw reason
        };
        switch (this.status) {
            case FULFILLED: {
                fulFilledFn(this.value);
                break;
            }
            case REJECTED: {
                rejectedFn(this.reason);
                break;
            }
        }
    }
    
    //检验是否为function
    isFunction(param) {
        return typeof param === 'function';
    }
 }
复制代码
4、首先要拿到所有的回调, 然后在某个时机去执行他. 需要新建两个数组, 分别存储成功和失败的回调, 调用then的时候, 如果还是pending就存入数组.
复制代码
class MyPromise {
    FULFILLED_CALLBACK_LIST = [] //存储成功回调
    REJECTED_CALLBACK_LIST = [] //存储失败回调
    .....
    
    then(onFulfilled, onRejected) {
        const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value) => value
        const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) => {
            throw reason
        };
        switch (this.status) {
            case FULFILLED: {
                fulFilledFn(this.value);
                break;
            }
            case REJECTED: {
                rejectedFn(this.reason);
                break;
            }
            case PENDING: {
                this.FULFILLED_CALLBACK_LIST.push(fulFilledFn);
                this.REJECTED_CALLBACK_LIST.push(rejectedFn);
                break;
            }
        }
    }
    
    //检验是否为function
    isFunction(param) {
        return typeof param === 'function';
    }
 }
复制代码
5、在status状态发生变化的时候调用数组里所有的函数
复制代码
class MyPromise {
   FULFILLED_CALLBACK_LIST = [] //存储成功回调
   REJECTED_CALLBACK_LIST = [] //存储失败回调
   .....
   
    resolve(value) {
       if (this.status === PENDING) {
          //这层判断是因为fulfilled状态只可以由pending状态改变而来
           this.status = FULFILLED;
           this.value = value;
           //执行存储的函数
           this.FULFILLED_CALLBACK_LIST.forEach(callback => {
               callback(this.value);
           });
       }
   }
   
   reject(reason) {
       if (this.status === PENDING) {
           //同理这层判断是因为rejected状态只可以由pending状态改变而来
           this.status = REJECTED;
           this.reason = reason;
           //执行存储的函数
           this.REJECTED_CALLBACK_LIST.forEach(callback => {
               callback(this.reason);
           });
       }
   }
   
   then(onFulfilled, onRejected) {
       const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value) => value
       const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) => {
           throw reason
       };
       switch (this.status) {
           case FULFILLED: {
               fulFilledFn(this.value);
               break;
           }
           case REJECTED: {
               rejectedFn(this.reason);
               break;
           }
           case PENDING: {
               this.FULFILLED_CALLBACK_LIST.push(fulFilledFn);
               this.REJECTED_CALLBACK_LIST.push(rejectedFn);
               break;
           }
       }
   }
   
   //检验是否为function
   isFunction(param) {
       return typeof param === 'function';
   }
}
复制代码
7、then的返回值
情况1:如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则新promise必须reject e
复制代码
class MyPromise {
   FULFILLED_CALLBACK_LIST = [] //存储成功回调
   REJECTED_CALLBACK_LIST = [] //存储失败回调
   .....
   
   then(onFulfilled, onRejected) {
       const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value) => value
       const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) => {
           throw reason
       };
       const fulFilledFnWithCatch = (resolve, reject) => {
           try {
               fulFilledFn(this.value);
           } catch (e) {
               reject(e)
           }
       };

       const rejectedFnWithCatch = (resolve, reject) => {
           try {
               rejectedFn(this.reason);
           } catch (e) {
               reject(e);
           }
       }
       switch (this.status) {
           case FULFILLED: {
               return new MyPromise(fulFilledFnWithCatch);
           }
           case REJECTED: {
               return new MyPromise(rejectedFnWithCatch);
           }
           case PENDING: {
               return new MyPromise((resolve, reject) => {
                   this.FULFILLED_CALLBACK_LIST.push(() => fulFilledFnWithCatch(resolve, reject));
                   this.REJECTED_CALLBACK_LIST.push(() => rejectedFnWithCatch(resolve, reject));
               });
           }
       }
   }
   
   //检验是否为function
   isFunction(param) {
       return typeof param === 'function';
   }
}
复制代码
情况2:如果onFulfilled不是函数且promise成功执行,那么新的promise必须返回同样的状态和val
情况3:如果onRejected不是函数且promise拒绝执行,那么新的promise必须返回同样的状态和reason
复制代码
class MyPromise {
   FULFILLED_CALLBACK_LIST = [] //存储成功回调
   REJECTED_CALLBACK_LIST = [] //存储失败回调
   .....
   
   then(onFulfilled, onRejected) {
       const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value) => value
       const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) => {
           throw reason
       };
       const fulFilledFnWithCatch = (resolve, reject) => {
           try {
               fulFilledFn(this.value);
               resolve(this.value);
           } catch (e) {
               reject(e)
           }
       };

       const rejectedFnWithCatch = (resolve, reject) => {
           try {
               rejectedFn(this.reason);
               if (this.isFunction(onRejected)) {
                   resolve();
               }
           } catch (e) {
               reject(e);
           }
       }
       switch (this.status) {
           case FULFILLED: {
               return new MyPromise(fulFilledFnWithCatch);
           }
           case REJECTED: {
               return new MyPromise(rejectedFnWithCatch);
           }
           case PENDING: {
               return new MyPromise((resolve, reject) => {
                   this.FULFILLED_CALLBACK_LIST.push(() => fulFilledFnWithCatch(resolve, reject));
                   this.REJECTED_CALLBACK_LIST.push(() => rejectedFnWithCatch(resolve, reject));
               });
           }
       }
   }
   
   //检验是否为function
   isFunction(param) {
       return typeof param === 'function';
   }
}
复制代码
情况4:如果onFulfilled或者onRejected 返回一个值 x ,则运行resolvePromise方法
复制代码
class MyPromise {
   FULFILLED_CALLBACK_LIST = [] //存储成功回调
   REJECTED_CALLBACK_LIST = [] //存储失败回调
   .....
   
   const fulFilledFnWithCatch = (resolve, reject, newPromise) => {
       try {
           if (!this.isFunction(onFulfilled)) {
               resolve(this.value);
           } else {
               const x = fulFilledFn(this.value);
               this.resolvePromise(newPromise, x, resolve, reject);
           }
       } catch (e) {
           reject(e)
       }
   };

   const rejectedFnWithCatch = (resolve, reject, newPromise) => {
       try {
           if (!this.isFunction(onRejected)) {
               reject(this.reason);
           } else {
               const x = rejectedFn(this.reason);
               this.resolvePromise(newPromise, x, resolve, reject);
           }
       } catch (e) {
           reject(e);
       }
   }

   switch (this.status) {
       case FULFILLED: {
           const newPromise = new MyPromise((resolve, reject) => fulFilledFnWithCatch(resolve, reject, newPromise));
           return newPromise;
       }
       case REJECTED: {
           const newPromise = new MyPromise((resolve, reject) => rejectedFnWithCatch(resolve, reject, newPromise));
           return newPromise;
       }
       case PENDING: {
           const newPromise = new MyPromise((resolve, reject) => {
               this.FULFILLED_CALLBACK_LIST.push(() => fulFilledFnWithCatch(resolve, reject, newPromise));
               this.REJECTED_CALLBACK_LIST.push(() => rejectedFnWithCatch(resolve, reject, newPromise));
           });
           return newPromise;
       }
   }
   
   //检验是否为function
   isFunction(param) {
       return typeof param === 'function';
   }
   
    resolvePromise(newPromise, x, resolve, reject){}
}
复制代码
8、resolvePromise
复制代码
    resolvePromise(newPromise, x, resolve, reject) {
        // 防止死循环
        if (newPromise === x) {
            return reject(new TypeError('The promise and the return value are the same'));
        }

        if (x instanceof MPromise) {
            x.then((y) => {
                resolvePromise(newPromise, y, resolve, reject);
            }, reject);
        } else if (typeof x === 'object' || this.isFunction(x)) {
            if (x === null) {
                return resolve(x);
            }
            let then = null;
            try {
                then = x.then;
            } catch (error) {
                return reject(error);
            }
            // 如果 then 是函数
            if (this.isFunction(then)) {
                let called = false;
                try {
                    then.call(
                        x,
                        (y) => {
                            if (called) return;
                            called = true;
                            resolvePromise(promise, y, resolve, reject);
                        },
                        (r) => {
                            if (called) return;
                            called = true;
                            reject(r);
                        });
                } catch (error) {
                    if (called) return;
                    reject(error);
                }
            } else {
                resolve(x);
            }
        } else {
            resolve(x);
        }
    }
复制代码
9、onFulfilled 和 onRejected 是微任务
复制代码
    then(onFulfilled, onRejected) {
        ...
        const fulFilledFnWithCatch = (resolve, reject, newPromise) => {
            queueMicrotask(() => {
                try {
                    if (!this.isFunction(onFulfilled)) {
                        resolve(this.value);
                    } else {
                        const x = fulFilledFn(this.value);
                        this.resolvePromise(newPromise, x, resolve, reject);
                    }
                } catch (e) {
                    reject(e)
                }
            })
        };

        const rejectedFnWithCatch = (resolve, reject, newPromise) => {
            queueMicrotask(() => {
                try {
                    if (!this.isFunction(onRejected)) {
                        reject(this.reason);
                    } else {
                        const x = rejectedFn(this.reason);
                        this.resolvePromise(newPromise, x, resolve, reject);
                    }
                } catch (e) {
                    reject(e);
                }
            })
        }

        switch (this.status) {
            case FULFILLED: {
                const newPromise = new MPromise((resolve, reject) => fulFilledFnWithCatch(resolve, reject, newPromise));
                return newPromise;
            }
            case REJECTED: {
                const newPromise = new MPromise((resolve, reject) => rejectedFnWithCatch(resolve, reject, newPromise));
                return newPromise;
            }
            case PENDING: {
                const newPromise = new MPromise((resolve, reject) => {
                    this.FULFILLED_CALLBACK_LIST.push(() => fulFilledFnWithCatch(resolve, reject, newPromise));
                    this.REJECTED_CALLBACK_LIST.push(() => rejectedFnWithCatch(resolve, reject, newPromise));
                });
                return newPromise;
            }
        }
    }
复制代码
10. catch方法
复制代码
catch (onRejected) {
    return this.then(null, onRejected);
}
复制代码
11. promise.resolve(静态方法)

将现有对象转为Promise对象,如果 Promise.resolve 方法的参数,不是具有 then 方法的对象(又称 thenable 对象),则返回一个新的 Promise 对象,且它的状态为fulfilled。
复制代码
static resolve(param) {
    if (param instanceof MyPromise) {
        return param;
    }

    return new MyPromise(function (resolve) {
        resolve(param);
    });
}
复制代码
12. promise.reject(静态方法)

返回一个新的Promise实例,该实例的状态为rejected。Promise.reject方法的参数reason,会被传递给实例的回调函数。
复制代码
static reject(reason) {
    return new MPromise((resolve, reject) => {
        reject(reason);
    });
}
复制代码
路漫漫其修远兮,每天记录一点点,争取不再做菜鸟
文章分类
前端
文章标签