2.ES6-Promise的实现

146 阅读3分钟

基础版本实现:

  1. then函数实现成功和失败函数的同步注册
  2. resolve和reject函数实现成功和失败函数的异步执行,并改变当前promsie的状态
  class PromiseA {
    constructor(fn) {
      this.status = PENDING;//状态
      this.value = undefined;
      this.error = undefined;
      this.onFulfilled = undefined;//成功处理函数
      this.onRejected = undefined;//失败处理函数
      fn(this.resolve.bind(this), this.reject.bind(this));
    }
    resolve(value) {
      if (this.status === PENDING) {
        setTimeout(() => {//保证为异步执行
          this.status = FULFILLED;//改变状态
          this.value = value;
          this.onFulfilled(this.value);
        }, 0)
      }
    }
    reject(error) {
      if (this.status === PENDING) {
        setTimeout(() => {//保证为异步执行
          this.status = REJECTED;//改变状态
          this.error = error;
          this.onRejected(this.error);
        }, 0)
      }
    }
    then(onFulfilled, onRejected) {
      //判断onFulfilled/onRejected是否是函数,给默认函数
      onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
      onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error };
      if (this.status === PENDING) {
        //如果状态是PENDING,将回调函数缓存,以供resolve/reject调用
        this.onFulfilled = onFulfilled;
        this.onRejected = onRejected;
      } else if (this.status === FULFILLED) {
        //如果状态是fulfilled,直接执行成功回调,并将成功值传入
        onFulfilled(this.value)
      } else {
        //如果状态是rejected,直接执行失败回调,并将失败原因传入
        onRejected(this.error)
      }
      return this;
    }
    catch(onRejected) {
      return this.then(null, onRejected);
    }
  }

完整版本实现:

1.根据Promises/A+规范,then函数每次都返回一个promise对象,详情如下:


  function resolvePromise(bridgePromise, x, resolve, reject) {
    if (x === bridgePromise) {
      return reject(new TypeError('循环引用'))
    }
    let called = false; // 避免多次调用
    if (x instanceof PromiseB) {//promise对象
      if (x.status === PENDING) {
        x.then(y => {
          resolvePromise(bridgePromise, y, resolve, reject)
        }, e => {
          reject(e)
        })
      } else {
        x.then(resolve, reject)
      }
    } else if (x && ((typeof x === 'object') || (typeof x === 'function'))) {
      try {
        // 是否是thenable对象(具有then方法的对象/函数)
        let then = x.then;
        if (typeof then === 'function') {
          //如果 then 是一个函数,以x为this调用then函数,且第一个参数是resolvePromise,第二个参数是rejectPromise
          then.call(x, y => {
            if (called) return;
            called = true;
            resolvePromise(bridgePromise, y, resolve, reject);
          }, e => {
            if (called) return;
            called = true;
            reject(e);
          })
        } else { // 说明是一个普通对象/函数
          resolve(x)
        }
      } catch (e) {
        if (called) return;
        called = true;
        reject(e);
      }

    }
    else {
      resolve(x)
    }
  }



  function gen(length, resolve) {
    let values = [],
      count = 0;
    return function (value, i) {
      values[i] = value;
      if (++count === length) {
        resolve(values)
      }
    }
  }


  class PromiseB {
    constructor(fn) {
      this.status = PENDING;
      this.value = undefined;
      this.error = undefined;
      this.onFulfilledCallbacks = [];//成功回调函数队列
      this.onRejectedCallbacks = [];//失败回调函数队列
      fn(this.resolve.bind(this), this.reject.bind(this))
    }
    static resolve(value) {
      return new PromiseB((resolve, reject) => {
        resolve(value);
      });
    }
    static reject(error) {
      return new PromiseB((resolve, reject) => {
        reject(error);
      });
    }
    static race(promises) {
      /**
      * Promise.race
      * 参数: 接收 promise对象组成的数组作为参数
      * 返回值: 返回一个Promise实例
      * 只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理(取决于哪一个更快)
      */
      return new PromiseB((resolve, reject) => {
        promises.forEach((promise, index) => {
          promise.then(resolve, reject);
        });
      });
    }
    static all(promises) {
      /**
        * Promise.all Promise进行并行处理
        * 参数: promise对象组成的数组作为参数
        * 返回值: 返回一个Promise实例
        * 当这个数组里的所有promise对象全部变为resolve状态的时候,才会resolve。
      */
      return new PromiseB((resolve, reject) => {
        let done = gen(promises.length, resolve);
        promises.forEach((promise, index) => {
          promise.then((value) => {
            done(index, value);//每次调用,会计算gen中缓存count,全部完成返回此时的数组value
          }, reject)
        })
      })
    }

    resolve(value) {
      if (this.status === PENDING) {
        setTimeout(() => {
          this.status = FULFILLED;
          this.value = value;
          this.onFulfilledCallbacks.forEach((callback) => {
            callback(this.value)
          })
        });
      }
    }
    reject(error) {
      if (this.status === PENDING) {
        setTimeout(() => {
          this.status = FULFILLED;
          this.error = error;
          this.onFulfilledCallbacks.forEach((callback) => {
            callback(this.error)
          })
        });
      }
    }
    then(onFulfilled, onRejected) {
      let bridgePromise;
      //处理onFulfilled/onRejected 不存在情况
      onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
      onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error };
      if (this.status === PENDING) {//等待状态
        return bridgePromise = new PromiseB((resolve, reject) => {
          this.onFulfilledCallbacks.push((value) => {
            try {
              let x = onFulfilled(value);//执行then中成功回调,value将在resolve中传入
              resolvePromise(bridgePromise, x, resolve, reject);//解析x
            } catch (e) {
              reject(e)
            }
          })
          this.onRejectedCallbacks.push((error) => {
            try {
              let x = onRejected(error);//执行then中错误回调,error将在reject中传入
              resolvePromise(bridgePromise, x, resolve, reject);//解析x
            } catch (e) {
              reject(e)
            }
          })
        })
      }
      if (this.status === FULFILLED) {//成功状态
        return bridgePromise = new PromiseB((resolve, reject) => {
          setTimeout(() => {//确保为异步执行
            try {
              let x = onFulfilled(this.value);
              resolvePromise(bridgePromise, x, resolve, reject);
            } catch (e) {
              reject(e)
            }

          });
        })
      }
      if (this.status === REJECTED) {//失败状态
        return bridgePromise = new PromiseB((resolve, reject) => {
          setTimeout(() => {
            try {
              let x = onRejected(this.error);
              resolvePromise(bridgePromise, x, resolve, reject);
            } catch (e) {
              reject(e)
            }
          });
        })
      }
    }
    catch(onRejected) {
      return this.then(null, onRejected);
    }

}