源码学习

es6 Promise 学习笔记3 Promise.all

2020-07-17  本文已影响0人  草祭木初

定义:Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败 promise 的结果。

它通常在启动多个异步任务并发运行并为其结果创建承诺之后使用,以便人们可以等待所有任务完成。

看下例子

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

  Promise.all([promise1, promise2, promise3]).then((values) => {
    console.log(values);
  }).catch ((e)=>{
    console.log('this is catch:',e)
  }).finally(()=>{
    console.log('this is finally:')
  });
// expected output: Array [3, 42, "foo"]

源码

export default function all(entries) {
// 这里的this是Promise
  return new Enumerator(this, entries).promise;
}

export default class Enumerator {
  constructor(Constructor, input) {
    this._instanceConstructor = Constructor;
// 这里new了个空的Promise
// 它的订阅者列表 [then,thenResolve,thenReject,catch,catchResolve,catchReject,finally,finallyResolve,finallyReject]
想不起来可以看下: [es6 Promise 学习笔记1 基础代码解析](http://jira.saicmobility.com:8090/pages/viewpage.action?pageId=275494365)
    this.promise = new Constructor(noop); 

    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) {
        fulfill(this.promise, this._result);
      } else {
        this.length = this.length || 0;
        this._enumerate(input);
        if (this._remaining === 0) {
          fulfill(this.promise, this._result);
        }
      }
    } else {
      reject(this.promise, validationError());
    }
  }
  _enumerate(input) {
// 这里的_state 是为了 只要有一个 reject了 就停止
    for (let i = 0; this._state === PENDING && i < input.length; i++) {
      this._eachEntry(input[i], i);
    }
  }

// 这里的 _eachEntry 与 invokeCallback 非常像
  _eachEntry(entry, i) {
    let c = this._instanceConstructor;
    let { resolve } = c;

    if (resolve === originalResolve) {
      let then;
      let error;
      let didError = false;
      try {
        then = entry.then;
      } catch (e) {
        didError = true;
        error = e;
      }

      if (then === originalThen &&
        entry._state !== PENDING) {
        this._settledAt(entry._state, i, entry._result);
      } else if (typeof then !== 'function') {
// 我们例子里有一个这种情况的 promise2 
        this._remaining--;
        this._result[i] = entry;
      } else if (c === Promise) {
// 这里new了 一个新的空的 Promise, c就是 调用 all的Promise
        let promise = new c(noop); // 我们叫这个promise 为promiseC吧
        if (didError) {
          reject(promise, error);
        } else {
// 大家可以 回忆一下这个函数做了什么
// 1,如果 entry 是Promise 则生成一个新的PromiseEntry 并且它的订阅者列表是 \[undefined, promiseEntryResolve, promiseEntryReject\]
//   而promiseEntryResolve(promiseC, value) 这个value是 PromiseEntry 生成并传进来的
// 2,如果不是 且 他的 then 不存在则 直接设定_result, 不过这种情况 被 上一个 if 拦截住了
// 3,还有一种情况是 传进来的Promise 不是我们的Promise 是另外一个实现,这种就不考虑了
// 这里其实与 学习笔记2里的 promise2的创建过程一样,
// entry 的resolve 或者 reject 触发后会将返回的结果 放到 promise的_result上,并将promise(promiseC)的状态改为 非 PENDING
          handleMaybeThenable(promise, entry, then);
        }
// 这个函数是 生成promiseC的订阅者列表\[undefined, promiseCResolve, promiseCReject\]
        this._willSettleAt(promise, i);
      } else {
        this._willSettleAt(new c(resolve => resolve(entry)), i);
      }
    } else {
      this._willSettleAt(resolve(entry), i);
    }
  }

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

    if (promise._state === PENDING) {
      this._remaining--; // 这里有个并发的问题?

      if (state === REJECTED) {
        reject(promise, value);
      } else {
        this._result[i] = value;
      }
    }

    if (this._remaining === 0) {
      fulfill(promise, this._result);
    }
  }

  _willSettleAt(promise, i) {
    let enumerator = this;
// promiseC 执行 因为 它的状态已经不是 PENDING了 所以它会 立即执行一个 异步操作并调用 回调enumerator._settledAt
    subscribe(
      promise, undefined,
      value => enumerator._settledAt(FULFILLED, i, value),
      reason => enumerator._settledAt(REJECTED, i, reason)
    );
  }
};

es6 Promise 学习笔记1 基础代码解析
es6 Promise 学习笔记2 链式调用
es6 Promise 学习笔记3 Promise.all
es6 Promise 学习笔记4 Promise.race

上一篇 下一篇

猜你喜欢

热点阅读