promise源码分析

源码取自:源码博客javascript

源码:html

class Promise2 {
  constructor(executor) { //executor执行器
    this.status = 'pending'; //默认等待状态
    this.value = undefined; //成功的值
    this.reason = undefined //失败的原用
    this.onResovleCallbacks = [];
    this.onRejectedCallbacks = [];
    let resolve = (value) => {
      if (this.status === 'pending') {
        this.status = 'resolved'; //成功
        this.value = value;
        this.onResovleCallbacks.forEach(fn => fn());
      }
    }
    let reject = (reason) => {
      if (this.status === 'pending') {
        this.status = 'rejected'; //失败
        this.reason = reason;
        this.onRejectedCallbacks.forEach(fn => fn());
      }
    }
    try {
      executor(resolve, reject); //默认上执行器执行
    } catch (e) { //捕获到异常时,直接走失败
      reject(e);
    }
  }

  then (onFufilled, onRejected) {
    onFufilled = typeof onFufilled === 'function' ? onFufilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : err => {
      throw err
    };
    function resolvePromise (promise2, x, resolve, reject) {
      //x多是别人的 promise ,因此尽量的容许别人瞎写
      if (promise2 === x) { //返回的结果和promise是同一个,那么永远不会成功
        return reject(new TypeError('循环引用'));
      }
      //
      let called;
      // 看x是否是promise。promise应该是一个对象
      if (x != null && (typeof x === 'object' || typeof x === 'function')) { //多是promise
        try {
          let then = x.then; // 若是是对象 我就试着取一下then方法 若是有then,认为它是promise
          if (typeof then === 'function') { // then是函数,是promise
            then.call(x, y => {
              // 成功和失败只能调用一个
              if (called) return;
              called = true;
              // resolve的结果依旧是promise 那就继续解析
              resolvePromise(promise2, y, resolve, reject);
            }, r => {
              if (called) return;
              called = true;
              reject(r); // 失败了就失败了
            })
          } else {
            resolve(x); // 直接成功便可
          }
        } catch (e) { // 取then出错了那就不要在继续执行了
          if (called) return;
          called = true;
          reject(e);
        }
      } else { //普通值 让promise2直接变成成功态
        resolve(x);
      }
    };
    let promise2; //返回的新promise

    
    promise2 = new this.constructor((resolve, reject) => {
      if (this.status === 'resolved') {
        // setTimeout(() => {
        try {
          let x = onFufilled(this.value); //x是上一个promise返回值,多是一个普通值,也多是一个promise;x也多是别人的promise,咱们能够写一个方法,统一处理
          resolvePromise(promise2, x, resolve, reject); //下一次then的实例promise2,此次返回值x,promise2的成功方法,promise2的失败方法
        } catch (e) {
          reject(e)
        }
        // }, 0);
      }
      if (this.status === 'rejected') {
        // setTimeout(() => {
        try {
          let x = onRejected(this.reason);
          // reject(x);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e)
        }
        // }, 0)
      }
      if (this.status === 'pending') {
        this.onResovleCallbacks.push(() => {
          // setTimeout(() => {
          try {
            let x = onFufilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
          // }, 0)
        });
        this.onRejectedCallbacks.push(() => {
          // setTimeout(() => {
          try {
            let x = onRejected(this.reason)
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
          // }, 0)
        })
      }
    });
    return promise2;
  }

  catch (onRejected) {
    return this.then(null, onRejected);
  }

  finally (onFinally) {
    return this.then(function (value) {
      return Promise.resolve(onFinally(value))
    }, function (reason) {
      return Promise.resolve(onFinally(reason))
    });
  }

  static resolve (data) {
    return new this((resovle) => {
      resovle();
    }).then(_ => {
      return data;
    })
  }

  static reject (data) {
    /* 与原生保持一致 */
    return new this((resolve, reject) => {
      reject(data);
    });

    /* 与Promise.resovle保持一致 */
    return new this((resolve, reject) => {
      reject();
    }).then(_ => {
      return data;
    })
  }

  static all (arr) {
    arr = Object.prototype.toString.call([]) === "[object Array]" ? arr : [arr];
    let length = arr.length;
    if (!length) return;
    return new this((resolve, reject) => {
      let result = [];
      let num = length;
      arr.forEach((item, index) => {
        /* 将item包装为promise */
        return new this(r => r())
          .then(_ => item)
          .then(_ => {
            result[index] = _;
            num--;
            num === 0? resolve(result):null;
          }, _ => {
            reject(_);
          })
      })
    })
  }

  static race(arr){
    arr = Object.prototype.toString.call([]) === "[object Array]" ? arr : [arr];
    let length = arr.length;
    if (!length) return;
    
    return new this((resolve,reject)=>{
      arr.forEach(item=>{
        new this(r=>r()).then(_=>item)
        .then(_=>{
          resolve(_);
        },_=>{
          reject(_);
        })
      })
    })
  }
}

Promise:java

1. 为了实现promise的链式调用,每一次的then,finally或catch后返回的都是一个全新的promise.promise

2.因为1的缘由,状态凝固也只在当前的promise中有效。函数

3.因为1的缘由,promise中的resolveArrs的长度老是<=1,rejectArrs同理。this

4.then方法是promise的核心,then的回调的方法:
   首先将返回值包装为一个promise,需排除回调方法不是当前promise自己,而后递归执行此promise,至为普通返回值,直接resolve(onResolve),或reject(onReject)
    
5. catch,finally 为then方法的特殊状况prototype

6. 链式中的then为微任务,须要所有早于当前周期中的全部setTimeout执行,全部不能加setTimeout;
   若不加,同时会带来另外一个问题:同一周期内此promise的then方法将所有提早于全部原生promise的then方法执行,不过不会出现即便有原生方法又使用此补丁的状况。
   二者比较,取后者影响更小code

7.Promise.resolve(data).then():data为常量或Promise,data为promise时, 状态会被data所改变,then中获取的为promise执行的结果htm

8.Promise.reject(data):data为常量或Promise,data为promise时,状态会被data所改变,then中获取的为promise自己对象

相关文章
相关标签/搜索