Promise

71 阅读5分钟

要深入理解Promise就自己实现一下Promise吧!不了解Promise的移步 👉🏻 Promise 入门

Promise实现

分析一下Promie的的实现

  1. Promise 是一个类,会传入一个Function,并立即执行

  2. Promise有三个状态:

    1. pending 进行中
    2. fulfilled 成功
    3. rejected 失败
  3. 状态只能由 Pending --> Fulfilled 或者 Pending --> Rejected,且一但发生改变便不可二次修改

  4. Promise中使用resolve和rejected改变状态

  5. then方法判断Promise状态

初始化一个Promise类

class MyPromise {
   PENDING = 'pending';
   FULFILLED = 'fulfilled';
   REJECTED = 'rejected';
   status; // 状态
   value = null; // 成功的返回的value
   reason = null; // 失败原因
   constructor(executor) {
       // 初始化状态
       this.status = this.PENDING;
       // 这是Promise接收的函数,立即执行
       executor(this._resolve,this._reject) // 传入Promise成功和失败的回调
   }
   
   // 失败的回调
  _reject(reason){
       // 修改状态为失败
      if (this.status === this.PENDING) {
          // 修改状态和reason值
          this.status = this.REJECTED;
          this.reason = reason;
      }
  }
  
   // 成功的回调
  _resolve(value){
      // 修改状态为成功
      if (this.status === this.PENDING) {
          // 修改状态和reason值
          this.status = this.FULFILLED;
          this.value = value;
      }
  }
  
}

现在就可以通过调用reject和resolve来改变MyPromise的状态了

再看看then的实现

then是用来判断状态的,接受两个函数
then(onFulfilled, onRejected){
    if (this.status === this.FULFILLED) {
        onFulfilled(this.value) // 调用成功的回调,返回value
    }
    if (this.status === this.REJECTED) {
        onRejected(this.reason) // 调用失败的回调,返回失败原因
    }
}

执行一下,发现并没有console

这里涉及到了js循环机制EventLoop ,then执行的时候resolve并没有执行,status还是pending状态;但是resolve执行的时候then已经执行过了,不会再执行了

这里再添加两个存储数组来存放成功和失败的回调 onFulfilledCallbacks、onRejectedCallbacks

class MyPromise {
   PENDING = 'pending';
   FULFILLED = 'fulfilled';
   REJECTED = 'rejected';
   status; // 状态
   value = null; // 成功的返回的value
   reason = null; // 失败原因
   onFulfilledCallbacks = [];
   onRejectedCallbacks = [];
   constructor(executor) {
       // 初始化状态
       this.status = this.PENDING;
       // 这是Promise接收的函数,立即执行
       executor(this._resolve.bind(this),this._reject.bind(this)) // 传入Promise成功和失败的回调
   }
   
   // 失败的回调
  _reject(reason){
       // 修改状态为失败
      if (this.status === this.PENDING) {
          // 修改状态和reason值
          this.status = this.REJECTED;
          this.reason = reason;
           while(this.onRejectedCallbacks.length) {
              // 执行失败队列中的回调
              this.onRejectedCallbacks.shift()(reason);
          }
      }
  }
  
   // 成功的回调
  _resolve(value){
      // 修改状态为成功
      if (this.status === this.PENDING) {
          // 修改状态和reason值
          this.status = this.FULFILLED;
          this.value = value;
          while(this.onFulfilledCallbacks.length) {
              // 执行成功队列中的回调
              this.onFulfilledCallbacks.shift()(value);
          }
      }
  }
  then(onFulfilled, onRejected){
    const onFulfilledCallback = () => {
        onFulfilled(this.value) // 调用成功的回调,返回value
    };
    const onRejectedCallback = () => {
         onRejected(this.reason) // 调用失败的回调,返回失败原因
    };
    // 状态为成功时
    if (this.status === this.FULFILLED) {
        onFulfilledCallback();
    }
   // 状态为失败时
    if (this.status === this.REJECTED) {
        onRejectedCallback();
    }
    // 状态为进行中
    if(this.status === this.PENDING) {
        // 把成功和失败的回调存到对应的队列
        this.onFulfilledCallbacks.push(onFulfilledCallback);
        this.onRejectedCallbacks.push(onRejectedCallback);
    }
  }
}

执行成功

then的链式调用

我们的then并没有返回结果,没法继续执行then方法

那就给then返回一个 新的Promise

then(onFulfilled, onRejected){
    const _this = this;
    return new MyPromise((resolve, reject) => {
        const onFulfilledCallback = () => {
            this.isPromise(onFulfilled(_this.value), resolve, reject); // 调用成功的回调,返回value
        };
        const onRejectedCallback = () => {
            this.isPromise(onRejected(_this.reason), resolve, reject); // 调用失败的回调,返回失败原因
        };
        // 状态为成功时
        if (_this.status === _this.FULFILLED) {
            onFulfilledCallback();
        }
       // 状态为失败时
        if (_this.status === _this.REJECTED) {
            onRejectedCallback();
        }
        // 状态为进行中
        if(_this.status === _this.PENDING) {
            // 把成功和失败的回调存到对应的队列
            _this.onFulfilledCallbacks.push(onFulfilledCallback);
            _this.onRejectedCallbacks.push(onRejectedCallback);
        }
    
    })

}
// 判断是不是Promise
isPromise(value, resolve, reject){
    if (value instanceof MyPromise){
        value.then(resolve, reject);
    } else {
        resolve(value)
    }
}

看看执行结果

链式调用成功

then链式调用识别返回的是不是Promise实例本身

原生Promise返回自身会报错

再把then修改一下

then(onFulfilled, onRejected){
    const _this = this;
    const promise = new MyPromise((resolve, reject) => {
        const onFulfilledCallback = () => {
            this.isPromise(promise, onFulfilled(_this.value), resolve, reject); // 调用成功的回调,返回value
        };
        const onRejectedCallback = () => {
            this.isPromise(promise, onRejected(_this.reason), resolve, reject); // 调用失败的回调,返回失败原因
        };
        // 状态为成功时
        if (_this.status === _this.FULFILLED) {
            onFulfilledCallback();
        } 
       // 状态为失败时
        if (_this.status === _this.REJECTED) {
            onRejectedCallback();
        }
        // 状态为进行中
        if(_this.status === _this.PENDING) {
            // 把成功和失败的回调存到对应的队列
            _this.onFulfilledCallbacks.push(onFulfilledCallback);
            _this.onRejectedCallbacks.push(onRejectedCallback);
        }
    
    })
    return promise;
}
// 判断是不是Promise
isPromise(promise, value, resolve, reject){
    if (promise === value) {
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if (value instanceof MyPromise){
        value.then(resolve, reject);
    } else {
        resolve(value)
    }
}

报错了,onRejected不是function

做一下容错

then(onFulfilled, onRejected){
    const _this = this;
    const realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
     const realOnRejected = typeof onRejected === 'function' ? onRejected : reason => new Error(reason);
    const promise = new MyPromise((resolve, reject) => {
        const onFulfilledCallback = () => {
            this.isPromise(promise, realOnFulfilled(_this.value), resolve, reject); // 调用成功的回调,返回value
        };
        const onRejectedCallback = () => {
            this.isPromise(promise, realOnRejected(_this.reason), resolve, reject); // 调用失败的回调,返回失败原因
        };
        // 状态为成功时
        if (_this.status === _this.FULFILLED) {
            onFulfilledCallback();
        } 
       // 状态为失败时
        if (_this.status === _this.REJECTED) {
            onRejectedCallback();
        }
        // 状态为进行中
        if(_this.status === _this.PENDING) {
            // 把成功和失败的回调存到对应的队列
            _this.onFulfilledCallbacks.push(onFulfilledCallback);
            _this.onRejectedCallbacks.push(onRejectedCallback);
        }
    
    })
    return promise;
}
// 判断是不是Promise
isPromise(promise, value, resolve, reject){
    if (promise === value) {
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if (value instanceof MyPromise){
        value.then(resolve, reject);
    } else {
        resolve(value)
    }
}

还是报错,promise初始化之前不允许访问

创建一个异步函数,等promise初始化完成后再去执行

then(onFulfilled, onRejected){
    const _this = this;
    const realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
     const realOnRejected = typeof onRejected === 'function' ? onRejected : reason => new Error(reason);
    const promise = new MyPromise((resolve, reject) => {
        const onFulfilledCallback = () => {
            queueMicrotask(this.isPromise(promise, realOnFulfilled(_this.value), resolve, reject));
            
        };
        const onRejectedCallback = () => {
            queueMicrotask(this.isPromise(promise, realOnRejected(_this.reason), resolve, reject)); // 调用失败的回调,返回失败原因
        };
        // 状态为成功时
        if (_this.status === _this.FULFILLED) {
            onFulfilledCallback();
        } 
       // 状态为失败时
        if (_this.status === _this.REJECTED) {
            onRejectedCallback();
        }
        // 状态为进行中
        if(_this.status === _this.PENDING) {
            // 把成功和失败的回调存到对应的队列
            _this.onFulfilledCallbacks.push(onFulfilledCallback);
            _this.onRejectedCallbacks.push(onRejectedCallback);
        }
    
    })
    return promise;
}

执行成功

catch方法

错误捕获

    catch (onRejected) { return this.then(undefined, onRejected) }
class MyPromise {
    PENDING = 'pending';
    FULFILLED = 'fulfilled';
    REJECTED = 'rejected';
    status; // 状态
    value = null; // 成功的返回的value
    reason = null; // 失败原因
    onFulfilledCallbacks = [];
    onRejectedCallbacks = [];
    constructor(executor) {
        try {
        // 初始化状态
            this.status = this.PENDING;
            // 这是Promise接收的函数,立即执行
            executor(
                this._resolve.bind(this),
                this._reject.bind(this)
            ) // 传入Promise成功和失败的回调
        } catch (error) {
            this._reject(error);
        }
        
    }

    // 失败的回调
    _reject(reason) {
        // 修改状态为失败
        if (this.status === this.PENDING) {
            // 修改状态和reason值
            this.status = this.REJECTED;
            this.reason = reason;
            while (this.onRejectedCallbacks.length) {
                // 执行失败队列中的回调
                this.onRejectedCallbacks.shift()(reason);
            }
        }
    }

    // 成功的回调
    _resolve(value) {
        // 修改状态为成功
        if (this.status === this.PENDING) {
            // 修改状态和reason值
            this.status = this.FULFILLED;
            this.value = value;
            while (this.onFulfilledCallbacks.length) {
                // 执行成功队列中的回调
                this.onFulfilledCallbacks.shift()(value);
            }
        }
    }
    then(onFulfilled, onRejected){
        const _this = this;
        const realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
        const realOnRejected = typeof onRejected === 'function' ? onRejected : reason => new Error(reason);
        const promise = new MyPromise((resolve, reject) => {
            const onFulfilledCallback = () => {
                try{
                    queueMicrotask(() => this.isPromise(promise, realOnFulfilled(_this.value), resolve, reject));
                } catch(error) {
                    reject(error);
                } 
                
            };
            const onRejectedCallback = () => {
                try{
                   // 调用失败的回调,返回失败原因
                   queueMicrotask(() => this.isPromise(promise, realOnRejected(_this.reason), resolve, reject));
                } catch(error) {
                     reject(error);                    
                }
                
            };
            // 状态为成功时
            if (_this.status === _this.FULFILLED) {
                onFulfilledCallback();
            } 
           // 状态为失败时
            if (_this.status === _this.REJECTED) {
                onRejectedCallback();
            }
            // 状态为进行中
            if(_this.status === _this.PENDING) {
                // 把成功和失败的回调存到对应的队列
                _this.onFulfilledCallbacks.push(onFulfilledCallback);
                _this.onRejectedCallbacks.push(onRejectedCallback);
            }
        
        })
        return promise;
    }
    catch (onRejected) { return this.then(undefined, onRejected) }
    // 判断是不是Promise
    isPromise(promise, value, resolve, reject){
        // console.log(promise,value)
        if (promise === value) {
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        }
        if (value instanceof MyPromise){
            value.then(resolve, reject);
        } else {
            resolve(value)
        }
    }
}

实现Promise 静态方法

static resolve(value){
    if (value instanceof MyPromise) return value;
    return new MyPromise((resolve) => resolve(value));
}
static reject(reason){
    if (reason instanceof MyPromise) return reason;
    return new MyPromise((resolve, reject) => reject(reason));
}
static all(list){
    return new MyPromise((resolve, reject) => {
        if (Array.isArray(list)) {
            reject(new TypeError('is not Array'))
        }
        let values = [];
        let promises = [...list];
        let count = 0;
        
        while(promises.length <=) {
            this.resolve(promises.shift()).then((res) => {
                count ++;
                values.push(res)
                if (count === promises.length) resolve(values);
            }, error => {
               return reject(error);  
            })
        }
    
    })
}

static race(list){
    return new MyPromise((resolve, reject) => {
        if (Array.isArray(list)) {
            reject(new TypeError('is not Array'))
        }
        let promises = [...list];
        
        while(promises.length <=) {
            this.resolve(promises.shift()).then((res) => {
               return resolve(values);
            }, error => {
               return reject(error);  
            })
        }
    
    })
}
static finally (cb) {
    return this.then(
          value  => MyPromise.resolve(cb()).then(() => value),
          reason => MyPromise.resolve(cb()).then(() => { throw reason })
    );
 };
 static allSettled(list) {
        return new MyPromise((resolve, reject) => {
            let arr = [];
            let count = 0;
            for (let p of list) {
                this.resolve(p).then(res => {
                    arr.push({ status: 'fulfilled', value: res});
                    count++;
                    if (count === list.length) {
                        resolve(arr);
                    }
                }).catch(error => {
                    arr.push({ status: 'rejected', reason: error});
                    count++;
                    if (count === list.length) {
                        resolve(arr);
                    }
                });
              };
        });
    }