查看MDN看起来传递给Promise.all的values
回调的then()
包含承诺顺序的值。例如:
var somePromises = [1, 2, 3, 4, 5].map(Promise.resolve);
return Promise.all(somePromises).then(function(results) {
console.log(results) // is [1, 2, 3, 4, 5] the guaranteed result?
});
有人可以引用说明values
应该在哪个订单中的规格吗?
答案 0 :(得分:198)
很快,保留订单。
根据您链接的规范,Promise.all(iterable)
将iterable
(即支持Iterator
接口的对象)作为参数,稍后调用PerformPromiseAll( iterator, constructor, resultCapability)
使用它,后者使用IteratorStep(iterator)
循环iterable
这意味着如果您传递给Promise.all()
的可迭代内容是严格排序的,那么一旦传入它们仍然会被订购。
解析是通过Promise.all() Resolve
实现的,其中每个已解析的promise都有一个内部[[Index]]
槽,它标记了原始输入中promise的索引。
所有这些意味着输出严格按输入进行排序,只要输入是严格排序的(例如,数组)。
你可以在下面的小提琴(ES6)中看到这个:
// Used to display results
const write = msg => {
document.body.appendChild(document.createElement('div')).innerHTML = msg;
};
// Different speed async operations
const slow = new Promise(resolve => {
setTimeout(resolve, 200, 'slow');
});
const instant = 'instant';
const quick = new Promise(resolve => {
setTimeout(resolve, 50, 'quick');
});
// The order is preserved regardless of what resolved first
Promise.all([slow, instant, quick]).then(responses => {
responses.map(response => write(response));
});
答案 1 :(得分:26)
是的,results
中的值与promises
的顺序相同。
有人可能会引用ES6 spec on Promise.all
,但由于使用了迭代器api和泛型promise构造函数,它有点复杂。但是,您会注意到每个解析器回调都有一个[[index]]
属性,该属性是在promise-array迭代中创建的,用于设置结果数组上的值。
答案 2 :(得分:23)
正如先前的答案已经说明的那样,Promise.all
使用与原始Promises的输入顺序相对应的数组聚合所有已解析的值(请参阅Aggregating Promises)。
但是,我想指出,订单只保留在客户端!
对于开发者来说,看起来Promise是按顺序完成的,但实际上,Promises以不同的速度处理。了解何时使用远程后端非常重要,因为后端可能会以不同的顺序接收您的Promise。
以下示例通过使用超时来说明问题:
<强> Promise.all 强>
const myPromises = [
new Promise((resolve) => setTimeout(() => {resolve('A (slow)'); console.log('A (slow)')}, 1000)),
new Promise((resolve) => setTimeout(() => {resolve('B (slower)'); console.log('B (slower)')}, 2000)),
new Promise((resolve) => setTimeout(() => {resolve('C (fast)'); console.log('C (fast)')}, 10))
];
Promise.all(myPromises).then(console.log)
在上面显示的代码中,三个Promises(A,B,C)被赋予Promise.all
。三个Promise以不同的速度执行(C是最快的,B是最慢的)。这就是Promise的console.log
语句按此顺序出现的原因:
C (fast)
A (slow)
B (slower)
如果Promises是AJAX调用,则远程后端将按此顺序接收这些值。但是在客户端Promise.all
确保根据myPromises
数组的原始位置对结果进行排序。这就是最终结果的原因:
['A (slow)', 'B (slower)', 'C (fast)']
如果您还想保证Promise的实际执行,那么您需要一个像Promise队列这样的概念。以下是使用p-queue的示例(请注意,您需要将所有Promise包装在函数中):
顺序承诺队列
const PQueue = require('p-queue');
const queue = new PQueue({concurrency: 1});
// Thunked Promises:
const myPromises = [
() => new Promise((resolve) => setTimeout(() => {
resolve('A (slow)');
console.log('A (slow)');
}, 1000)),
() => new Promise((resolve) => setTimeout(() => {
resolve('B (slower)');
console.log('B (slower)');
}, 2000)),
() => new Promise((resolve) => setTimeout(() => {
resolve('C (fast)');
console.log('C (fast)');
}, 10))
];
queue.addAll(myPromises).then(console.log);
<强>结果强>
A (slow)
B (slower)
C (fast)
['A (slow)', 'B (slower)', 'C (fast)']