ES6-Promise 源码阅读

·  阅读 2505

前言

此次阅读的 promise 实现是 ES6-Promise ,是 promise 的众多实现中较为完善的一个例子,从入口文件 lib/es6-promise/promise.js 开始阅读,可以看到 Promise 定义有如下的静态方法

Promise.all

Promise.race

Promise.resolve

Promise.reject

以及挂载在 Promise.protoype 上的方法

Promise.prototype.then

Promise.prototype.catch

Promise.prototype.finally

接下来会对其核心代码进行解读。

Promise的三种状态

Promise规范中定义了promise的三种状态,而且promise的状态更新只能是以下两种情况,一旦状态发生改变之后就不能再修改:

  • PENDING -> FULFILLED
  • PENDING -> REJECTED

ES6-Promise 内部中的定义如下:

// void 运算符 对表达式进行求值,结果都返回 undefined
// 可以防止undefined被重写,如:const undefined = xxx
const PENDING = void 0; // undefined
const FULFILLED = 1;
const REJECTED = 2;

Promise的使用例子

我们来看一个Promise的使用例子,传入一个resolver函数,初始化一个promise实例。resolver函数会被立即执行,并且可以使用promise内部传入的两个参数 resolve 和 reject ,resolve 和 reject都是函数,接收一个参数, value 或者 reason,在resolver函数内部调用 resolve 或者 reject ,都会更新promise的状态 。

具体调用例子如:

const promise = new Promise(function(resolve, reject) {
  if (/* 异步操作成功 */){
    // 更新状态为 fulfilled 并缓存 value
    resolve(value);
  } else {
    // 更新状态为 rejected  并缓存 reason
    reject(error);
  }
});

为了响应promise不同的状态(fulfilled 或 rejected),可以通过实例的 then 方法绑定回调函数:

promise.then( 
    // resolver 中 resolve 的 value
    value => { /* pending -> fulfilled 时调用 */
    },
    // resolver 中 reject 的 resaon
    reason => { /* pending -> rejected 时调用 */
    }
)

这样就完成了一个promise的基本使用。

Promise的构造函数

由上面的基本调用开始,先看看promise的构造方法:

class Promise {

  constructor(resolver) {

    // export const PROMISE_ID = Math.random().toString(36).substring(2); 
    // nextId() 返回一个自增的闭包变量
    // Promise实例的唯一标识
    this[PROMISE_ID] = nextId();

    // 初始化变量
    // _result 缓存 resolve 时的 value 或者 reject 时的 reason
    // _state  缓存 promise 的 当前状态 初始化为 pending
    this._result = this._state = undefined;
    // 订阅序列
    this._subscribers = [];

    // noop = ()=>{}  内部定义的一个空函数
    // 内部调用时: new Promise(noop) 不会经过下面的初始化过程

    // 外部调用时: 对传入参数进行检查
    if (noop !== resolver) {
      // 条件1:resolver 必须要是一个函数
      typeof resolver !== 'function' && needsResolver();
      // 条件2: 必须通过 new Promise() 初始化实例
      this instanceof Promise ? initializePromise(this, resolver) : needsNew();
      // 符合以上条件的进行初始化
      // initializePromise() 函数
    }
  }

可以看到promise的构造方法完成了以下的工作:

  • 初始化变量

    [PROMISE_ID] : 该实例独一无二的ID

    result: 缓存value或者reason

    subscribers: 订阅promise状态变化的序列(后面会讲到)

  • 对入参 resolver 进行判断

    resolver === noop noop是内部定义的一个空函数,此时 promise 会初始化结束。

    resolver !==  noop resolver 必须是函数,同时必须是通过 new Promise() 初始化实例。满足以上两个条件的,就会调用 initializePromise ,对实例进一步初始化,其代码如下:

function initializePromise(promise, resolver) {
  try {
    // 立即执行 resolver函数 
    // 传入包装好的参数
    resolver(function resolvePromise(value) {
      resolve(promise, value);
    }, function rejectPromise(reason) {
      reject(promise, reason);
    });
  } catch (e) {
    // 代码发生异常 
    // 则直接更新 promise 的状态为 rejected
    reject(promise, e);
  }
}

可以看到,resolver函数被立即执行了,而且在 resolver 函数中调用的 resolve 和 reject 就是 resolvePromise 和 rejectPromise 函数,这也是promise提供给resolver的两个入参,它们包装了内部实现的 resolve 和 reject 函数。

再来看看内部的 resolve和 reject 是如何对promise状态进行更新的。

内部的 reject 函数

reject函数较为简单:

/** 
 * pending => rejected
 */
function reject(promise, reason) {
  // 状态一旦改变就不可逆转
  if (promise._state !== PENDING) {
    return;
  }
  // 缓存处理结果 更新promise状态
  promise._state = REJECTED;
  promise._result = reason;
  // 注:asap 函数暂不详细解释 后面源码中多次用到 
  // asap(func,param) 可以理解为立即执行 func(param)
  // promise 的状态发生了改变 通知订阅者
  asap(publishRejection, promise);
}

promise的状态更新为rejected后,会通过publishRejection向订阅序列发出通知,publishRejection函数代码如下,具体的publish函数封装了如何向订阅序列发出通知的逻辑,后续会说到:

function publishRejection(promise) {
  // ???
  // onError 好像一直都是null啊
  if (promise._onerror) {
    promise._onerror(promise._result);
  }
  // promise的状态发生了改变
  // 向订阅序列发出通知
  publish(promise);
}

内部的 resolve 函数

resolve 则会对 value 的类型进行判断,情况有以下:

  • value是实例本身,更新promise的状态为 rejected,不允许resolve本身
  • value是对象或者函数,调用 handleMaybeThenable()方法进行特殊处理
  • 其他情况,调用 fulfill 方法更新状态

具体代码逻辑如下:

function resolve(promise, value) {
  if (promise === value) {
    // 1. 不允许 value 是 promise实例本身
    // 更新为 rejected 状态 
    reject(promise, selfFulfillment());
  } else if (objectOrFunction(value)) {
    // 2. value是对象或者函数 
    handleMaybeThenable(promise, value, getThen(value));
  } else {
    // 3. 其他数据类型
    fulfill(promise, value);
  }
}

先看看 fulfill 方法,方法不难理解,就是更新promise的状态为 fulfilled 同时向订阅序列发出通知。

 /**
 * pedding => fulfilled
 */
function fulfill(promise, value) {
  // promise状态不可逆
  if (promise._state !== PENDING) {
    return;
  }
  // 缓存处理结果 修改promise状态
  promise._result = value;
  promise._state = FULFILLED;
  // promise的状态发生了改变
  // 向订阅序列发出通知
  if (promise._subscribers.length !== 0) { 
    asap(publish, promise);
  }
}

再来看看当 resolve 函数传入的value是对象或者函数,调用特殊处理的 handleMaybeThenable(promise,value,getThen(value))方法。其中getThen方法接收一个参数promise,用于尝试获取promise的then属性,会捕获错误,返回包装的错误对象。函数内部又对value进行了进一步划分。

handleMaybeThenable的具体代码如下:

function handleMaybeThenable(promise, maybeThenable, then) {
  if (
    maybeThenable.constructor === promise.constructor &&
    then === originalThen &&
    maybeThenable.constructor.resolve === originalResolve) {
    // 1. resolve的值是一个 promise 实例 
    // 即通过 new Promise() 新建的实例
    handleOwnThenable(promise, maybeThenable);
  } else {
    // 2. 获取 value 的 then 属性时发生错误
    // 更新 promise 的 状态为 rejected
    if (then === TRY_CATCH_ERROR) {
      reject(promise, TRY_CATCH_ERROR.error);
      TRY_CATCH_ERROR.error = null;
    } else if (then === undefined) {
      // 3. 虽然 resolve的值是 函数或者对象 但不存在 then 属性
      // 按照普通数据类型进行处理
      fulfill(promise, maybeThenable);
    } else if (isFunction(then)) {      
      // 4. resolve的值是一个 thenable 对象, 具有then属性,并且为函数
      handleForeignThenable(promise, maybeThenable, then);
    } else {
      // 5. then 是其他数据类型 直接进行处理
      fulfill(promise, maybeThenable);
    }
  }
}

重新总结一下 resolve 的值分为以下情况:

  1. value为 promise 实例,调用handleOwnThenable方法进行处理
  2. value为 thenable 实例(一个具有then方法的对象),调用handleForeThenable方法进行处理
  3. 其他情况,直接调用 fulfill 方法处理值

第一种情况中,handleOwnThenable 具体代码如下:

/**
 * resolve 的值 value 是一个 promise 实例 
 * @param promise 当前的promise
 * @param thenable value
 */
function handleOwnThenable(promise, thenable) {
  // 检查 thenable 状态
  if (thenable._state === FULFILLED) {
    // FULFILLED 状态 
    // 使用 thenable 内部缓存的处理结果 
    // 作为 value 调用 fulfill 更新状态
    fulfill(promise, thenable._result);
  } else if (thenable._state === REJECTED) {
    // REJECTED  状态 
    // 使用 thenable 内部缓存的处理结果 
    // 作为 reason 调用 reject 更新状态
    reject(promise, thenable._result);
  } else {
    // pending 状态, 对 thenable 增加监听
    // 当 thenable 的状态改变时 
    // 用其结果缓存 更新 promise 的状态
    subscribe(thenable, undefined,
      value => resolve(promise, value),
      reason => reject(promise, reason))
  }
}

也就是说,当resolve的value是一个promise时,原封不动地返回这个promise。

第二种情况,当为一个具有then属性并且then为函数的对象时:

// let thenable = {
//   then: function(resolve, reject) {
//     resolve(42);
//   }
// };
function handleForeignThenable(promise, thenable, then) {
  asap(promise => {
    // 用一个 sealed 保证只能调用一次    
    var sealed = false;

    // tryThen 方法
    // 1. 以 thenable 作为执行上下文 
    // 2. 传入 (value=>{} , reason=>{}) 参数
    // 3. 执行 then 函数
    // 
    var error = tryThen(then, thenable, value => {
      if (sealed) {
        return;
      }
      sealed = true;

      if (thenable !== value) {
        // 如果 resolve 的 value 不是原来的thenale对象
        // 进一步对value进行处理(有可能又是一个promise实例或者thenable对象,或者其他情况...)
        resolve(promise, value);
      } else {
        // 如果 resolve 的 value 还是原来的thenale对象
        // 则直接 fulfill 这个对象
        // 不再进一步通过 resolve 避免死循环 
        fulfill(promise, value);
      }
    }, reason => {
      if (sealed) {
        return;
      }
      sealed = true;
      // then 方法 reject(‘xx')
      reject(promise, reason);
    }, 'Settle: ' + (promise._label || ' unknown promise'));


    // if error
    // rejected 状态
    if (!sealed && error) {
      sealed = true;
      reject(promise, error);
    }
  }, promise);
}

也就是说,当resolve的值是一个thenable对象时,会执行其then方法,根据then方法中调用入参resolve或者reject时传入的value或reason来对promise的状态进行更新。

subscribe 订阅机制

之前有提到promise的订阅,在Promise初始化的时候,声明了一个内部变量,用来存储对promise的订阅序列。

// 订阅序列
this._subscribers = [];

然后可以调用 subscribe 函数注册监听:

/**
 * @param {promise} parent         被订阅状态变化的Promise
 * @param {promise} child          订阅状态变化的Promise(可为undefined)
 * @param {function} onFulfillment 状态变化为 fulfilled 的订阅函数 
 * @param {function} onRejection   状态变化为 rejected  的订阅函数
 */
function subscribe(parent, child, onFulfillment, onRejection) {
  let { _subscribers  } = parent;
  let { length } = _subscribers;
  parent._onerror = null;
  // 每调用一次subscribe函数 订阅序列会增加三个元素
  _subscribers[length] = child;
  _subscribers[length + FULFILLED] = onFulfillment;
  _subscribers[length + REJECTED] = onRejection;

  // 有可能是在 parent 状态更新之后增加的订阅
  // 此时的订阅序列被清空 状态不再发生变化 则直接发出通知
  if (length === 0 && parent._state) {
    asap(publish, parent);
  }
}

可以看到,对一个promise订阅其状态更新时,会在其订阅序列增加三个参数,子promise(可为空),状态变为fulfilled时的回调,变为rejected时的回调。当一个promise状态更新之后,就会触发publish函数,发布修改,publish的具体代码逻辑如下:

/**
 * Promise状态更新 发出通知
 * @param {Promise} promise 
 */
function publish(promise) {
  // 所有订阅序列
  let subscribers = promise._subscribers;
  // promise的状态
  let settled = promise._state;
  // 订阅序列为空
  if (subscribers.length === 0) {
    return;
  } 
  /**
   * child:    订阅状态变化的promise
   * callback: 回调函数
   * detail:   value或者reason缓存
   */
  let child, callback,
    detail = promise._result; 
  // 每三个元素为一个订阅单位
  // 格式如: child + fufilled + rejected
  for (let i = 0; i < subscribers.length; i += 3) {
    // child === [object Promise]
    child = subscribers[i];
    // 根据 promsie 的状态获取相应的回调函数
    callback = subscribers[i + settled];
    // 情况1: 存在promise实例订阅
    if (child) {
      invokeCallback(settled, child, callback, detail);
    } else {
      // 情况2: 触发响应的回调函数
      callback(detail);
    }
  }
  // 清空监听数组 
    promise._subscribers.length = 0;
}

每三个元素为一个单位,publish函数会依次判断订阅者:

  1. 订阅存在子promise,存在则再调用 invokeCallback 函数
  2. 订阅不存在,直接传入结果缓存value或者reason 调用相应的回调函数

第一种情况下:

/**
 * settled  :  被监听promise的状态
 * promise  :  订阅监听的promise
 * callback :  fullfled | rejected 
 * detial   :  value | reason
 */
function invokeCallback(settled, promise, callback, detail) {

  let hasCallback = isFunction(callback),
    value, error, succeeded, failed;

  if (hasCallback) {
    // 尝试执行回调函数
    // 发生错误时 则返回 TRY_CATCH_ERROR 对象
    value = tryCatch(callback, detail);

    // 执行cb函数时出错
    if (value === TRY_CATCH_ERROR) {
      // 获取error的值
      failed = true;
      error = value.error;
      value.error = null;
    } else {
      // 设置状态
      succeeded = true;
    }
    // 不允许回调函数返回了原有的promise实例
    if (promise === value) {
      reject(promise, cannotReturnOwn());
      return;
    }
  } else {
    // 不存在回调函数
    value = detail;
    succeeded = true;
  }

  // 更新 promise 的状态
  if (promise._state !== PENDING) {
    // noop
  } else if (hasCallback && succeeded) {   // 回调函数存在的情况
    // value 是回调函数的返回值
    resolve(promise, value);
  } else if (failed) {
   // error 是调用回调函数的错误时的原因
    reject(promise, error);
  } else if (settled === FULFILLED) {   // 回调函数不存在的情况
    // 直接使用父promise的value
    fulfill(promise, value);
  } else if (settled === REJECTED) {
   
    reject(promise, value);
  }
}

总结一下,订阅一个promise 的状态变化,主要有两种情况:

  1. 一种是仅传入了回调函数,不存在子promise订阅,此时会promise的状态一旦变化,就会传入value或者reason,调用相应的回调函数。
  2. 另一种是订阅存在子promise,此时promise的状态一旦变化,又会分成回调函数有无两种情况, 有回调函数的话,传入value或者reason到相应的回调函数执行,回调函数的返回值作为结果缓存到子promise。 无回调函数的话,就直接使用value或者reason作为结果缓存。

Promise.prototype.then

方法传入两个函数参数,当promise的状态更新后,调用相应的回调函数,同时返回一个新的promise。

export default function then(onFulfillment, onRejection) {
  // 当前的 promise
  const parent = this;

  // 新建一个 promise
  // new pormise(()=>{})
  // [!] 通过此方式创建的 promise 不会进行 initializePromise 方法初始化
  // initializePromise 会执行传入的函数 空函数不需要执行 只需要初始化相关变量
  const child = new this.constructor(noop);

  // 仅初始化状态变量
  // promise[PROMISE_ID] = id++;
  // promise._state = undefined;
  // promise._result = undefined;
  // promise._subscribers = [];
  if (child[PROMISE_ID] === undefined) {
    makePromise(child);
  }

  // 获取当前 promise 的状态
  const { _state } = parent;

  // 当前的 promise 为 fullfied / rejected 
  // 直接处理
  if (_state) {
    // state = fullfied   ===> onFulfillment
    // state = rejected   ===> onRejection
    // 获取与状态对应的处理函数
    const callback = arguments[_state - 1];
    // 传入结果立即执行
    // 更新新建promise的状态
    asap(() => invokeCallback(_state, child, callback, parent._result));
  } else {
    // 当前的 promise 为 pending 
    // 将新建的 promise 绑定在 当前 promise 上
    // 当前的 pormise 状态改变之后 同步新建的 promise 状态
    subscribe(parent, child, onFulfillment, onRejection);
  }  
  // 返回新建的 promise
  return child;
}

总结一下,首先 then 方法会返回一个新的promise,其状态和原来的 promise 同步,结果缓存则有以下的两种情况。

  1. 如果设置了回调函数(onFulfillment或onRejection),会将原有promise的value或者reason传入回调函数,回调函数的返回结果缓存到新的promise实例中。
  2. 如果没有设置回调函数,会将原有的promise的value或者reason直接缓存给新的promise实例。

也就是下面的两种例子:

// 1. 第一种情况
let promise = new Promise((resolve,reject)=>{
    resolve('OK')
})
let child1 = promise.then((value)=>{
    return value + 'child1'
},()=>{})
// 此时child1的结果缓存是 'OKchild1'

// 2. 第二种情况
let child2 = promise.then().then().then().then().then( value =>{
    console.log(value) // 结果缓存还是最开始那个promise 也就是 'OK'
})

Promise.protoype.catch

catch方法是then方法的语法糖,通常我们会这样设置回调:

let promise = new Promise((resolve,reject)=>{

    if(/* 异步OK*/){
        resolve('OK')
    }else{
        reject(new Error('something wrong'))
    }
}).then(value=>{
    // xxx
}).catch(err=>{
    // xxx
})

// 但实际上等同于
promise.then( value=>{},err=>{})

其代码也很简单:

  /**
   * Promise.prototype.catch
   */
  catch (onRejection) {
    return this.then(null, onRejection);
  }

Promise.prototype.finally

finally方法用于无论状态发生了什么改变(fulfilled或者rejected)都要执行的操作,来自ES2018的标准。 注意:代码中的Promise.resolve 可先看看下面关于此方法的解读。

  /**
   * Promise.prototype.finally
   */
  finally(callback) {
    // 当前 promise
    let promise = this;
    // Promise
    let constructor = promise.constructor;

    if (isFunction(callback)) {
      // Promise.resolve 包裹成一个promise,再调用其 then 方法返回一个新的promise
      return promise.then(
        // pending -> fulfilled
        value => constructor.resolve(callback()).then(() => value),
        // pending -> rejected
        reason => constructor.resolve(callback()).then(() => {
          throw reason;
        }));
    }
    // callback 不是函数
    return promise.then(callback, callback);
  }

Promise.resolve

方法接收一个参数,返回一个Promise,可接受的输入情况有:


// 1. 传入的是一个 promise实例 
// 直接返回这个实例
Promise.resolve(promise);

// 2. 传入的是一个 thenable实例
// 执行 thenable  的 then 方法 
// 根据 方法内部 resolve 或者 reject 得到的 value 或者 resaon
// 设置为 promise 的状态和结果缓存
let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};
Promise.resolve(theanable);

// 3. 普通数据值 返回一个 fulfilled 状态的 promise
// 结果缓存为其 value
Promise.resolve(value);

具体代码实现如下


export default function resolve(object) {
  // Promise.resolve = Resolve;
  // [ Promise ] 
  let Constructor = this;

  // 1. 传入一个 promise 实例
  // 则直接返回这个promise
  if (object 
    && typeof object === 'object' 
    && object.constructor === Constructor) {
    return object;
  }

  // 新建一个空的 promise
  // 不会经过 initialPromise() 方法的初始化
  let promise = new Constructor(noop);

  // 2. 可能是 thenable 对象
  //    或者是其他普通值
  _resolve(promise, object);
  // 返回 promise
  return promise;
}

Promise.reject

方法较为简单,接收一个参数reason,直接返回一个状态为rejected的promise实例。

export default function reject(reason) {
  // Promise.reject
  // Promise
  let Constructor = this;
  // new Promise(()=>{})
  // 不会经过 initialPromise() 方法的初始化
  let promise = new Constructor(noop);
  // pending -> rejected
  _reject(promise, reason);
  // 返回promise
  return promise;
}

Promise.race

方法传入一个 数组,一般传入多个promise,包装成一个promise返回,这个promise的状态和传入的多个promise中最先更新状态那一个promise同步。

export default function race(entries) {
  // Promise
  let Constructor = this;

  if (!isArray(entries)) {
    // 不是数组 返回一个状态为rejected的Promise实例
    return new Constructor((_, reject) => reject(new TypeError('You must pass an array to race.')));
  } else {
    // 返回一个新的 Promise 实例 
    return new Constructor((resolve, reject) => {
      let length = entries.length;
      for (let i = 0; i < length; i++) {
        // Promise.resolve(entries[i]).then(resolve,reject)
        // 遍历所有元素 用 Promise.resolve() 包装成 Promise实例
        // 最先的一个 Promise 更新了状态后 都会同步外层 Promise 
        Constructor.resolve(entries[i]).then(resolve, reject);
      }
    });
  }
}

Promise.all

方法也是传入一个数组,一般传入多个promise,包装成一个promise返回,其状态有以下两种情况: 1 : 所有promise的状态都变成fulfilled时,返回的promise状态为fulfilled,结果是所有promise返回值的数组 2 : 有一个promise的状态率先变为rejected,返回的promise状态为rejected,结果是这个promise rejected的返回值

代码如下:

// Promise.all
export default function all(entries) {
  // 初始化一个 Enumerator 实例 返回其属性 promise
  return new Enumerator(this, entries).promise;
}

Enumerator的具体代码如下:


export default class Enumerator {
  constructor(Constructor, input) {

    // Promise
    this._instanceConstructor = Constructor;

    // 新建一个空的promise 不会经过 initialPromise() 方法的初始化
    // Promise.all() 最后返回这个值
    this.promise = new Constructor(noop);

    // 初始化
    // promise[PROMISE_ID] = id++;
    // promise._state = undefined;
    // promise._result = undefined;
    // promise._subscribers = [];
    if (!this.promise[PROMISE_ID]) {
      makePromise(this.promise);
    }

    if (isArray(input)) {
      // 总长度
      this.length = input.length;
      // 剩余长度
      this._remaining = input.length;
      // 存放结果
      this._result = new Array(this.length);

      if (this.length === 0) {
        // 空数组
        // 返回一个状态为 fulfilled 的promise
        fulfill(this.promise, this._result);
      } else {
        this.length = this.length || 0;
        // 执行 _enumerate
        this._enumerate(input);

        if (this._remaining === 0) {
          // 剩余长度为0
          // 返回一个状态为 fulfilled 的promise
          fulfill(this.promise, this._result);
        }
      }
    } else {
      // 入参不是数组
      // 返回一个状态为r ejected 的promise
      reject(this.promise, validationError());
    }
  }
  _enumerate(input) {
    // 遍历执行所有状态为 pending 的 promise
    for (let i = 0; this._state === PENDING && i < input.length; i++) {
      this._eachEntry(input[i], i);
    }
  }

  _eachEntry(entry, i) {
    // Promise.all() 方法 传入的是 Promise 
    let c = this._instanceConstructor;
    //                     Promise.resolve
    let { resolve } = c;

    // Promise.resolve = Promise.resolve
    if (resolve === originalResolve) {
     
      // 尝试获取 entry 的 then 属性
      let then = getThen(entry);

      if (then === originalThen 
        && entry._state !== PENDING) {
        // then  === Promise.prototype.then
        // 情况1: entry是promise实例 同时 状态不为 pending        
        this._settledAt(entry._state, i, entry._result);
      } else if (typeof then !== 'function') {
        // then 不为函数 为普通值
        // 直接设置
        this._remaining--;
        this._result[i] = entry;
      } else if (c === Promise) {// true 在Promise.all() 中此处一直成立        
        let promise = new c(noop);
        // then 是一个函数      
        // 对 then 进行进一步检查 如果是一个 thenable 对象 
        // let thenable = {
        //       then: function(resolve,reject)=>{ resolve('66')} 
        // }
        // 则会执行 then 方法 获取相应的值后设置 promise 的状态
        handleMaybeThenable(promise, entry, then);
        // 设置监听
        this._willSettleAt(promise, i);
      } else {
        // 情况2: entry是promise实例 状态为 pending 
        // 绑定监听 待entry状态改变之后 再设置相应的值 
        this._willSettleAt(new c(resolve => resolve(entry)), i);
      }
    } else {
      // 其他情况  这里不作考虑  
      // 因为Promise.all 传入的是Promise  
      this._willSettleAt(resolve(entry), i);
    }
  }

  _settledAt(state, i, value) {
    let {
      promise
    } = this;

    if (promise._state === PENDING) {
      // 又完成了一个 Promise
      this._remaining--;

      if (state === REJECTED) {
        // 一旦有一个promise实例状态变为rejected
        // 更新状态为rejected
        reject(promise, value);
      } else {// fulfilled
        // 更新值
        this._result[i] = value;
      }
    }

    if (this._remaining === 0) {
      // 所有的元素都已经变为 fulfilled
      // 同步返回promise的状态
      fulfill(promise, this._result);
    }
  }

  _willSettleAt(promise, i) {
    let enumerator = this;
    // 绑定监听
    // promise的状态改变后 调用相应的函数
    subscribe(
      promise, undefined,
      value => enumerator._settledAt(FULFILLED, i, value),
      reason => enumerator._settledAt(REJECTED, i, reason)
    );
  }
};

以上便是es6-promise核心代码的阅读。

最后

原文地址:链接

ES6-Promise仓库地址: 链接

分类:
前端
分类:
前端
收藏成功!
已添加到「」, 点击更改