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