MDN文档对Promise的解释是: Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。
民间也有一种说法是: Promise是优雅解决异步回调函数嵌套地狱问题的一种解决方案。
- Promise/A+是Promise的一个开放的标准或者是规范,它规范了Promise的术语和要求(包括Promise的三种状态、必须提供一个then方法和Promise的解决流程)。
- ECMAScript 6里面的Promise是Promise/A+规范的一种实现方案。它是一个规范的具体的一种实现方案,它在原有的Promise/A+规定上扩展了一些API:
Promise.prototype.catch()
Promise.prototype.finally()
Promise.allSettled()
Promise.all()
Promise.race()
Promise.any()
Promise.reject()
Promise.resolve()
下面是一个实现了Promsoe/A+规范同时也扩展了ECMAScript6的PromiseAPI的源码并且含有大量注释。(通过了所有promises-aplus-test的测试案例)
如果你也想测试你自己编写的Promsie是否符合**Promise/A+**规范可以下载一个 “promises-aplus-test” 的工具来测试。下面是安装命令:
npm install promises-aplus-tests -g
下面是promises-aplus-test的用法:
Promise.deferred = function() {
const deferred = {
}
deferred.promise = new Promise((resolve, reject) => {
deferred.resolve = resolve
deferred.reject = reject
})
return deferred
}
module.exports = Promise;
在你编写的promise文件的末尾添加这些代码然后在命令行运行下面命令就可以
promises-aplus-tests 你要测试的文件名.js
const PEDDING = "pending",
FULFILLED = "fulfilled",
REJECTED = "rejected";
function isPromise(val) {
return (
val !== undefined &&
val !== null &&
(typeof val === 'object' || typeof val === 'function') &&
typeof val.then === 'function'
);
}
/**
* @todo The Promise Resolution Procedure=>Promise的解决流程
* @description Promise/A+ 规范
* 的承诺解决过程是一个抽象的操作作为输入一个承诺和一个值,它表示我们作为[[Resolve]](promise, x)。如果x是可能的,则在行为至少类似于承诺的假设下,
* 尝试promise采用的状态。否则,它将满足value 。xxpromisex只要对约定的实现公开Promises / A +兼容的then方法,对约定的实现就可以进行互操作。
* 它还允许Promises / A +实现以合理的then方法“同化”不合格的实现。
要运行[[Resolve]](promise, x),请执行以下步骤:
2.3.1 如果promise和x引用相同的对象,promise则以拒绝TypeError为理由。
2.3.2 如果x是一个承诺,则采用其状态[ 3.4 ]:
2.3.2.1 如果x未决,则promise必须保持未决状态,直到x实现或被拒绝。
2.3.2.2 如果/何时x满足,promise则以相同的值满足。
2.3.2.3 如果/何时x被拒绝,promise则以相同的理由拒绝。
2.3.3 否则,如果x是对象或函数,
2.3.3.1 我们then是x.then。[ 3.5 ]
2.3.3.2 如果检索属性x.then中抛出的异常的结果e,拒绝promise与e作为的原因。
2.3.3.3 如果then是函数,请使用xas this,第一个参数resolvePromise和第二个参数进行调用rejectPromise,其中:
2.3.3.3.1 如果/何时resolvePromise使用值调用y,请运行[[Resolve]](promise, y)。
2.3.3.3.2 如果/当rejectPromise是带一个理由r,拒绝promise与r。
2.3.3.3.3 如果同时调用resolvePromise和rejectPromise,或者对同一参数进行了多次调用,则第一个调用优先,而所有其他调用均被忽略。
2.3.3.3.4 如果调用then引发异常e,
2.3.3..3.4.1 如果resolvePromise或rejectPromise已经被调用,则忽略它。
2.3.3..3.4.2 否则,拒绝promise与e作为的原因。
2.3.3.4 如果then不是一个函数,实现promise用x。
2.3.4 如果x不是一个对象或功能,实现promise与x。
如果使用参与循环的可循环链的可转换组件来解决承诺,从而[[Resolve]](promise, thenable)最终导致递归性质[[Resolve]](promise, thenable)被再次调用,
则遵循上述算法将导致无限递归。鼓励但不是必需的实现,以检测这种递归并promise以提供信息TypeError为理由的拒绝。[ 3.6 ]
* @param {Promise} promise2
* @param {*} x
* @param {Function} resolve
* @param {Function} reject
* @returns {void}
*/
function resolvePromise(promise2, x, resolve, reject) {
//如果promise和x引用相同的对象,promise则以拒绝TypeError为理由。
/**
* 例子:
* const p=new Promise((resolve,reject)=>{
* resolve(xxx);
* }).then(v=>{
* return p;
* })
*/
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
//保证promise2的onFulfilled或者onRejected只被调用一次 防止多次调用
//比如:
/**
* new Promise((resolve,reject)=>{
* resolve(xxx);
* reject(xxx);
* resolve(xxx);
* });
* 这样就会导致promise2的onFulfilled或者onRejected被多次调用
*/
let called = false;
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
//then be x.then=>取出then
const then = x.then;
// 如果then是函数,就默认是promise了
if (typeof then === 'function') {
then.call(x,
//If/when resolvePromise is called with a value y, run [[Resolve]](promise, y).=> 如果/何时resolvePromise使用值调用y,请运行[[Resolve]](promise, y)。
(y) => {
//只能调用一次
if (called) return;
called = true;
//如果y依旧是一个promise 那么就递归解析
/**
* 例子:
* new Promose((resolve,reject)=>{
* resolve('xxx');
* }).then((v)=>{
* return new Promise((resolve,reject)=>{
* setTimeout(()=>{
* resolve(new Promise((resolve,reject)=>{
* resolve(new Promise((resolve,reject)=>{
* resolve(new Promise(...);//嵌套地狱
* }))
* }))
* }13000)
* })
* })
*/
resolvePromise(promise2, y, resolve, reject);
},
//If/when rejectPromise is called with a reason r, reject promise with r.=> 如果/当rejectPromise是带一个理由r,拒绝promise与r。
(r) => {
//只能调用一次
if (called) return;
called = true;
reject(r);
});
} else {
resolve(x);
}
} catch (e) {
//取then失败或者流程报错走到这里
if (called) return;
called = true;
reject(e);
}
} else {
//If x is not an object or function, fulfill promise with x.=>如果x不是一个对象或者函数
resolve(x);
}
}
class Promise {
/**
* @description Promise 构造器主要用于包装不支持promise(返回值不是Promise)的函数。
* @param {*} executor
*/
constructor(executor) {
if (isPromise(executor)) {
// Promise 构造器主要用于包装不支持promise(返回值不是Promise)的函数
throw new TypeError("Promise resolver # is not a function" );
}
//私有属性 这里为什么是callbacks(一个事件队列)?请看下面的例子:
/**
* const promise=new Promise((resolve,reject)=>{...});
* promise.then(...);
* promise.then(...);
* promise.then(...);
* promise.then(...);
* ...可以无穷尽也
* 根据promise/A+规范 所有的onFulfilled或者onRejected必须按照原调用顺序执行 所以这里才是一个队列
*/
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
this.onFinallyCallbacks = [];
this.reason = undefined;
this.value = undefined;
this.state = PEDDING;
const reject = (reason) => {
if (this.state === PEDDING) {
this.state = REJECTED;
//reason=reject(xxx)中传递的xxx
this.reason = reason;
this.onRejectedCallbacks.forEach(callback => callback());
this.onFinallyCallbacks.forEach(callback => callback());
}
}
const resolve = (value) => {
if (this.state === PEDDING) {
this.state = FULFILLED;
//value=resolve(xxx)中传递的xxx
this.value = value;
this.onFulfilledCallbacks.forEach(callback => callback());
this.onFinallyCallbacks.forEach(callback => callback());
}
}
try {
executor && typeof executor === 'function' && executor(resolve, reject);
} catch (err) {
reject(err);
}
}
/**
* @todo //规范:
// 当一个 Promise 完成(fulfilled)或者失败(rejected)时,返回函数将被异步调用(由当前的线程循环来调度完成).
具体的返回值依据以下规则返回。如果 then 中的回调函数:
// 返回了一个值,那么 then 返回的 Promise 将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值。
// 没有返回任何值,那么 then 返回的 Promise 将会成为接受状态,并且该接受状态的回调函数的参数值为 undefined。
// 抛出一个错误,那么 then 返回的 Promise 将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值。
// 返回一个已经是接受状态的 Promise,那么 then 返回的 Promise 也会成为接受状态,
并且将那个 Promise 的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值。
// 返回一个已经是拒绝状态的 Promise,那么 then 返回的 Promise 也会成为拒绝状态,
并且将那个 Promise 的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。
// 返回一个未定状态(pending)的 Promise,那么 then 返回 Promise 的状态也是未定的,并且它的终态与那个 Promise 的终态相同;
同时,它变为终态时调用的回调函数参数与那个 Promise 变为终态时的回调函数的参数是相同的。
* @param {*} onFulfilled 当 Promise 变成接受状态(fulfilled)时调用的函数。该函数有一个参数,即接受的最终结果(the fulfillment value)。
* 如果该参数不是函数,则会在内部被替换为 (x) => x,即原样返回 promise 最终结果的函数
* @param {*} onRejected 当 Promise 变成拒绝状态(rejected)时调用的函数。该函数有一个参数,即拒绝的原因(rejection reason)。
* 如果该参数不是函数,则会在内部被替换为一个 "Thrower" 函数 (it throws an error it received as argument)。
* @returns {Promise}
*/
then(onFulfilled, onRejected) {
if (typeof onFulfilled != 'function') {
//如果该参数不是函数,则会在内部被替换为 (x) => x,即原样返回 promise 最终结果的函数
onFulfilled = (x) => x;
}
if (typeof onRejected != 'function') {
// 如果该参数不是函数,则会在内部被替换为一个 "Thrower" 函数 (it throws an error it received as argument)
onRejected = (reason) => {
throw reason };
}
//偷懒函数 少写重复代码
const handler = (promise2, valueOrReason, onFOrR, resolve, reject) => {
try {
const result = onFOrR(valueOrReason);
resolvePromise(promise2, result, resolve, reject);
} catch (e) {
reject(e);
}
}
const promise2 = new Promise((resolve, reject) => {
try {
if (this.state === PEDDING) {
//当前Promise处于pedding状态下 则将onFulfilled和onRejected加入回调队列中 等待Promise的状态被改变时调用
this.onFulfilledCallbacks.push(
() => {
//这里为什么用setTimeout? =>2.2.4: `onFulfilled` or `onRejected` must not be called until the execution context stack contains
//only platform code. Clean-stack execution ordering tests (fulfillment case) when the promise is fulfilled asynchronously
//timeout of 200ms exceeded. Ensure the done() callback is being called in this test
setTimeout(() => {
/**
* resolvePromise这个是对 最顶层的Promise嵌套问题
* 这里的处理promise/A+并没有规范,但是ESCMSCript6的Promise扩展了这个功能,所以把es6的扩展也实现一下
* 例子:
* const new Promose((resolve,reject)=>{
* resolve(new Promise((resolve,reject)=>{
* new Promise(...)
* }))
* })
*/
resolvePromise(
promise2,
this.value,
(v) => {
handler(promise2, v, onFulfilled, resolve, reject); },
(r) => {
handler(promise2, r, onRejected, resolve, reject); }
);
}, 0);
// setTimeout(() => handler(promise2, this.value, onFulfilled, resolve, reject), 0);
}
);
this.onRejectedCallbacks.push(
() => {
setTimeout(() => handler(promise2, this.reason, onRejected, resolve, reject), 0);
}
);
} else if (this.state === FULFILLED) {
//当前Promise处于fulfilled状态下 则“直接调用” 这里通过setTimeout来执行异步任务
setTimeout(() => {
resolvePromise(
promise2,
this.value,
(v) => {
handler(promise2, v, onFulfilled, resolve, reject); },
(r) => {
handler(promise2, r, onRejected, resolve, reject); }
);
}, 0);
} else if (this.state === REJECTED) {
//当前Promise处于rejected状态下 则“直接调用” 这里通过setTimeout来执行异步任务 模拟微任务
setTimeout(() => handler(promise2, this.reason, onRejected, resolve, reject), 0);
}
} catch (err) {
//整个exctutor运行发生异常 则直接reject
reject(err);
}
});
return promise2;
}
/**
* @todo 规范: catch() 方法返回一个Promise (en-US),并且处理拒绝的情况。它的行为与调用Promise.prototype.then(undefined, onRejected) 相同。
* (事实上, calling obj.catch(onRejected) 内部calls obj.then(undefined, onRejected)).
*
* @description catch 方法可以用于您的promise组合中的错误处理。
* @param {*} onRejected 当Promise 被rejected时,被调用的一个Function。 该函数拥有一个参数:reason rejection 的原因。
* 如果 onRejected 抛出一个错误或返回一个本身失败的 Promise , 通过 catch() 返回的Promise 被rejected;否则,它将显示为成功(resolved)。
* @returns {Promise}
*/
catch (onRejected) {
//事实上, calling obj.catch(onRejected) 内部calls obj.then(undefined, onRejected)
return this.then(undefined, onRejected);
}
/**
* @todo 规范: finally() 方法返回一个Promise。在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。
* 这为在Promise是否成功完成后都需要执行的代码提供了一种方式。这避免了同样的语句需要在then()和catch()中各写一次的情况。
* @description 如果你想在 promise 执行完毕后无论其结果怎样都做一些处理或清理时,finally() 方法可能是有用的。
finally() 虽然与 .then(onFinally, onFinally) 类似,它们不同的是:
调用内联函数时,不需要多次声明该函数或为该函数创建一个变量保存它。
由于无法知道promise的最终状态,所以finally的回调函数中不接收任何参数,它仅用于无论最终结果如何都要执行的情况。
与Promise.resolve(2).then(() => {}, () => {}) (resolved的结果为undefined)不同,Promise.resolve(2).finally(() => {}) resolved的结果为 2。
同样,Promise.reject(3).then(() => {}, () => {}) (resolved 的结果为undefined), Promise.reject(3).finally(() => {}) rejected 的结果为 3。
注意: 在finally回调中 throw(或返回被拒绝的promise)将以 throw() 指定的原因拒绝新的promise.
* @param {*} onFinally
* @returns {Promise} 返回一个设置了 finally 回调函数的Promise对象。
*/
finally(onFinally) {
return new Promise((resolve, reject) => {
if (this.state == FULFILLED) {
setTimeout(() => {
try {
onFinally();
resolve(this.value);
} catch (err) {
reject(err);
}
}, 0);
} else if (this.state === REJECTED) {
setTimeout(() => {
try {
onFinally();
resolve(this.reason);
} catch (err) {
reject(err);
}
}, 0);
} else if (this.state === PEDDING) {
this.onFinallyCallbacks.push(() => {
try {
onFinally();
resolve(this.state === FULFILLED ? this.value : this.reason);
} catch (err) {
reject(err);
}
});
}
});
}
/**
* @static 静态方法
* @description 规范: Promise.resolve(value)方法返回一个以给定值解析后的Promise 对象。如果这个值是一个 promise,那么将返回这个 promise;
* 如果这个值是thenable(即带有"then" 方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;
* 否则返回的promise将以此值完成。此函数将类promise对象的多层嵌套展平。
* @warning 不要在解析为自身的thenable 上调用Promise.resolve。这将导致无限递归,因为它试图展平无限嵌套的promise。
* @param {*} value
* @returns {Promise}
*/
static resolve(value) {
return new Promise((resolve, reject) => {
if (isPromise(value)) {
value.then(resolve, reject);
} else {
resolve(value)
}
});
}
/**
* @todo Promise.reject()方法返回一个带有拒绝原因的Promise对象。
* @static
* @description 静态函数Promise.reject返回一个被拒绝的Promise对象。通过使用Error的实例获取错误原因reason对调试和选择性错误捕捉很有帮助。
* @param {*} reason
* @returns {Promise}
*/
static reject(reason) {
return new Promise((_, reject) => {
reject(reason);
});
}
/**
* @todo 规范: Promise.all() 方法接收一个promise的iterable类型(注:Array,Map,Set都属于ES6的iterable类型)的输入,
* 并且只返回一个Promise实例, 那个输入的所有promise的resolve回调的结果是一个数组。这个Promise的resolve回调执行是在
* 所有输入的promise的resolve回调都结束,或者输入的iterable里没有promise了的时候。它的reject回调执行是,只要任何一个输入的
* promise的reject回调执行或者输入不合法的promise就会立即抛出错误,并且reject的是第一个抛出的错误信息。
* @description Promise.allSettled()不管参数中的promise是fulfilled还是rejected,都会等参数中的实例都返回结果,包装实例才会结束。
* Promise.all()只有在接受的所有promise实例全部是fulfilled才会走Promise.all([p1,p2,p3]).then()方法,
* 只要有其中一个promise实例是rejected,就会直接走catch方法,并且catch中只会返回第一个变成rejected的promise的错误
* @param {*} iterable
* @returns {Promise} 规范: 如果传入的参数是一个空的可迭代对象,则返回一个已完成(already resolved)状态的 Promise。
如果传入的参数不包含任何 promise,则返回一个异步完成(asynchronously resolved) Promise。
注意:Google Chrome 58 在这种情况下返回一个已完成(already resolved)状态的 Promise。
其它情况下返回一个处理中(pending)的Promise。这个返回的 promise 之后会在所有的 promise
都完成或有一个 promise 失败时异步地变为完成或失败。
返回值将会按照参数内的 promise 顺序排列,而不是由调用 promise 的完成顺序决定。
*/
static all(iterable) {
return new Promise((resolve, reject) => {
try {
let values = [],
len = 0, //用来标记已迭代元素的数量 因为iterable可能是用户自定义迭代器对象(没有length或者size属性)。
isWalkComplete = false,
promiseList = [], //用一个数组保存住按照iterable中的排序的所有promise对象
promise;
const getSortPromiseValue = () => promiseList.map(p => p.value);
for (const iter of iterable) {
promise = !isPromise(iter) ? /***传入的参数里面不是promise,将它转变成promise***/ Promise.resolve(iter) : iter;
promiseList.push(promise); //复制或者说保存当前顺序的promise的引用
//执行then方法
promise.then(
(v) => {
values.push(v);
if (
typeof iterable === 'string' ||
Array.isArray(iterable) ||
iterable instanceof Map ||
iterable instanceof Set
) {
if (values.length === (iterable.length || iterable.size)) {
//处理返回值的顺序
values = getSortPromiseValue();
resolve(values);
}
} else if (isWalkComplete && values.length === len) {
//处理返回值的顺序
values = getSortPromiseValue();
resolve(values)
}
},
reason => reject(reason) //传入第一个发生reject的reason
); //then end
len++;
} //end for
isWalkComplete = true;
} catch (err) {
reject(err);
}
});
}
/**
* @todo 该Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,
* 并带有一个对象数组,每个对象表示对应的promise结果。
当您有多个彼此不依赖的异步任务成功完成时,或者您总是想知道每个promise的结果时,通常使用它。
相比之下,Promise.all() 更适合彼此相互依赖或者在其中任何一个reject时立即结束
* @param {*} iterable 一个可迭代的对象,例如Array,其中每个成员都是Promise。
* @returns {Promise} 一旦所指定的 promises 集合中每一个 promise 已经完成,无论是成功的达成或被拒绝,未决议的 Promise将被异步完成。
* 那时,所返回的 promise 的处理器将传入一个数组作为输入,该数组包含原始 promises 集中每个 promise 的结果。
对于每个结果对象,都有一个 status 字符串。如果它的值为 fulfilled,则结果对象上存在一个 value 。如果值为 rejected,
则存在一个 reason 。value(或 reason )反映了每个 promise 决议(或拒绝)的值。
*/
static allSettled(iterable) {
return new Promise((resolve, reject) => {
//已经完成了的Promose 不管是状态是fulfilled还是rejected
let completePromiseList = [],
promiseList = [],
len = 0,
completePromiseCount = 0,
isWalkComplete = false;
const getSortPromiseStatus = () => {
return promiseList.map(p => {
return {
status: p.state,
[p.state === FULFILLED ? 'value' : 'reason']: p.state === FULFILLED ? p.value : p.reason
}
});
};
for (const x of iterable) {
let promise = !isPromise(x) ? Promise.resolve(x) : x;
promiseList.push(promise);
promise.finally(() => {
completePromiseCount++;
if (isWalkComplete && completePromiseCount === len) {
completePromiseList = getSortPromiseStatus();
resolve(completePromiseList);
}
});
len++;
}
isWalkComplete = true;
});
}
/**
* @todo Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
* @description race 函数返回一个 Promise,它将与第一个传递的 promise 相同的完成方式被完成。
* 它可以是完成( resolves),也可以是失败(rejects),这要取决于第一个完成的方式是两个中的哪个。
如果传的迭代是空的,则返回的 promise 将永远等待。
如果迭代包含一个或多个非承诺值和/或已解决/拒绝的承诺,则 Promise.race 将解析为迭代中找到的第一个值。
* @param {*} iterable 可迭代对象,类似Array。详见 iterable。
* @returns {Promise} 一个待定的 Promise 只要给定的迭代中的一个promise解决或拒绝,就采用第一个promise的值作为它的值,
* 从而异步地解析或拒绝(一旦堆栈为空)。
*/
static race(iterable) {
return new Promise((resolve, reject) => {
for (const iter of iterable) {
//如果迭代包含一个或多个非承诺值和/或已解决/拒绝的承诺,则 Promise.race 将解析为迭代中找到的第一个值。
if (isPromise(iter)) {
//如果iter是个promise
const promise = iter;
//判断promise的状态来动态选择接受或者拒绝
if (promise.state === FULFILLED) {
promise.then(resolve);
} else if (promise.state === REJECTED) {
promise.then(undefined, reject);
} else if (promise.state === PEDDING) {
promise.then(resolve, reject);
}
} else {
//非promise类型直接resolve
resolve(iter)
}
}
});
}
/**
* @todo ECMAScript6的文档规范: Promise.any() 接收一个Promise可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。
* 如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise 和AggregateError类型的实例,
* 它是 Error 的一个子类,用于把单一的错误集合在一起。本质上,这个方法和Promise.all()是相反的。
* @description 这个方法用于返回第一个成功的 promise 。只要有一个 promise 成功此方法就会终止,它不会等待其他的 promise 全部完成。
不像 Promise.all() 会返回一组完成值那样(resolved values),我们只能得到一个成功值(假设至少有一个 promise 完成)。
当我们只需要一个 promise 成功,而不关心是哪一个成功时此方法很有用的。
同时, 也不像 Promise.race() 总是返回第一个结果值(resolved/reject)那样,这个方法返回的是第一个 成功的 值。
这个方法将会忽略掉所有被拒绝的 promise,直到第一个 promise 成功。
* @warning Promise.any() 方法依然是实验性的,尚未被所有的浏览器完全支持。它当前处于 TC39 第四阶段草案(Stage 4)
* @param {*} iterable 一个可迭代的对象, 例如 Array、Set、Map、String
* @returns {Promise} 如果传入的参数是一个空的可迭代对象,则返回一个 已失败(already rejected) 状态的 Promise。
如果传入的参数不包含任何 promise,则返回一个 异步完成 (asynchronously resolved)的 Promise。
其他情况下都会返回一个处理中(pending) 的 Promise。 只要传入的迭代对象中的任何一个 promise 变成成功(resolve)
状态,或者其中的所有的 promises 都失败,那么返回的 promise 就会 异步地(当调用栈为空时)
变成成功/失败(resolved/reject)状态。
*/
static any(iterable) {
return new Promise((resolve, reject) => {
let len = 0, //记录迭代器中元素的数量
isWalkComplete = false, //标识迭代器遍历完成
promiseList = [], //用一个数组保存住按照iterable中的排序的所有promise对象
errors = []; //记录所有的错误
const getSortPromiseReason = () => promiseList.map(p => p.reason);
for (const iter of iterable) {
if (isPromise(iter)) {
const promise = iter;
promiseList.push(promise);
promise.then(
v => {
resolve(v);
return;
},
reason => {
errors.push(reason);
//迭代器遍历完成 但是所有的promise值都失败了
if (isWalkComplete && errors.length === len) {
//获取排序后的promise的reason
errors = getSortPromiseReason();
reject(new AggregateError(errors, 'All promises were rejected'));
}
}
);
} else {
resolve(iter);
}
len++;
}
isWalkComplete = true;
//判断迭代器是否为空
if (len === 0) {
reject(new AggregateError(errors, 'All promises were rejected'));
}
});
}
}