promise源码分析

三世轮回 提交于 2020-12-03 14:13:11

源码取自:源码博客

源码:


(function (factory, global) {

  if (typeof module === 'object' && typeof module.export === 'object') {
    module.export = factory(global);
  } else if (typeof define === 'function' && (define.cmd || define.amd)) {
    factory(global);
  } else {
    factory(global);
  }

})(function (global, undefined) {

  class Promise {
    constructor(executor) { //executor执行器

      this.status = 'pending'; //默认状态:等待
      this.value = undefined; //成功的值
      this.reason = undefined //失败的值
      this.callBacks = [];  //暂存后续的执行

      let resolve = (value) => {
        if (this.status === 'pending') {
          this.status = 'resolved'; //成功
          this.value = value;
          this.callBacks.forEach(args => this.runCallBacks(args));
        }
      }
      let reject = (reason) => {
        if (this.status === 'pending') {
          this.status = 'rejected'; //失败
          this.reason = reason;
          this.callBacks.forEach(args => this.runCallBacks(args));
        }
      }

      this._abort = reject;

      this.runCallBacks = (args) => {
        let { onFufilled, onRejected, resolve, reject } = args;

        try {
          let temp;
          if (this.status === 'resolved') {
            // 即使回调为空,也不能影响后面的then,catch等方法
            temp = onFufilled ? onFufilled(this.value) : this.value;
          } else if (this.status === 'rejected') {
            temp = onRejected ? onRejected(this.reason) : this.reason;
          }

          if (temp && typeof temp.then === 'function' && temp instanceof this.constructor) {
            temp.then(value => {
              resolve(value);
            }, reason => {
              reject(reason);
            });
          } else {
            resolve(temp);
          }
        } catch (error) {
          reject(error);
        }
      }

      try {
        executor(resolve, reject); //默认上执行器执行
      } catch (e) { //捕获到异常时,直接走失败
        reject(e);
      }
    }

    then(onFufilled, onRejected) {

      return new this.constructor((resolve, reject) => {
        // 模拟异步(微任务),但是没有直接的定义微任务的api,所以暂用宏任务
        setTimeout(() => {
          let args = { onFufilled, onRejected, resolve, reject };
          if (this.status === 'pending') {
            this.callBacks.push(args);
          } else {
            this.runCallBacks(args);
          }
        }, 0)
        
      })
    }

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

    finally(onFinally) {
      return this.then(value => {
        return onFinally(value);
      }, reason => {
        return onFinally(reason)
      });
    }

    abort(reason = 'aborted') {
      this._abort(reason);
    }

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

    static reject(data) {
      /* 与原生保持一致 */
      return new this((resolve, reject) => {
        reject(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 = [];
        arr.forEach((item, index) => {
          return new this(r => r(item))
            .then(res => {
              result[index] = res;
              length--;
              length === 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(item))
            .then(_ => {
              resolve(_);
            }, _ => {
              reject(_);
            })
        })
      })
    }
  }
  global.Promise = Promise;
}, typeof window !== 'undefined' ? window : this);

Promise:

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

2.由于1的原因,状态凝固也只在当前的promise中有效。

3.由于1的原因,promise中的resolveArrs的长度总是<=1,rejectArrs同理。

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

6. 链式中的then为微任务,需要全部早于当前周期中的所有setTimeout执行,加setTimeout只为模拟效果,和原生的promise有一定的执行顺序差异(js目前没有);
   若不加,同时会带来另一个问题:同一周期内此promise的then方法将全部提前于所有原生promise的then方法执行,不过不会出现即使有原生方法又使用此补丁的情况。

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

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!