Promise.all:解析值的顺序
Promise.all: Order of resolved values
查看MDN,看起来传递给Promise.all then()
回调的values
包含按promise顺序排列的值。例如:
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
应该按哪个顺序排列吗?
PS:像这样运行代码表明这似乎是真的,尽管这当然不是证据 - 这可能是巧合。
很快,顺序被保留。
按照您链接到的规范,Promise.all(iterable)
将iterable
作为参数并在内部调用PerformPromiseAll(iterator, constructor, resultCapability)
,后者使用 IteratorStep(iterator)
循环iterable
。
解析是通过Promise.all() Resolve
实现的,其中每个解析的承诺都有一个内部[[Index]]
槽,该槽标记原始输入中承诺的索引。
所有这些都意味着输出是严格排序的,因为您传递给 Promise.all() 的可迭代对象是严格排序的(例如,数组)。
您可以在下面的小提琴(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));
});
正如前面的答案已经指出的,Promise.all
将所有解析的值聚合为对应于原始 Promise 输入顺序的数组(请参阅聚合 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))
];
Promise.all(myPromises).then(console.log)
在上面显示的代码中,三个承诺(A,B,C)被赋予Promise.all
。三个承诺以不同的速度执行(C是最快的,B是最慢的)。这就是为什么承诺的console.log
陈述按以下顺序显示:
C (fast)
A (slow)
B (slower)
如果承诺是 AJAX 调用,则远程后端将按此顺序接收这些值。但在客户端,Promise.all
确保结果根据myPromises
数组的原始位置进行排序。这就是为什么最终结果是:
['A (slow)', 'B (slower)', 'C (fast)']
如果你还想保证你的承诺的实际执行,那么你需要一个像承诺队列这样的概念。下面是一个使用 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)']
,results
中的值与promises
的顺序相同。
有人可能会在Promise.all
上引用ES6规范,尽管由于使用了迭代器API和通用承诺构造函数,它有点复杂。但是,您会注意到每个解析器回调都有一个 [[index]]
属性,该属性是在 promise-array 迭代中创建的,用于设置结果数组的值。
- ajax请求的顺序总是不同的
- 按照选项卡索引的顺序循环一个jQuery选择
- 匹配一个单词,其中候选人可以跨越顺序组(跨度)
- 按顺序添加和删除类
- 按我自己的类克隆另一个元素的内容和顺序
- Nested Q.all nodejs
- Javascript-根据赋值顺序,按键合并对象数组
- 2个backbone.js集合,具有相同的模型,但排序顺序不同
- querySelector/getElementByClassName嵌套项的顺序
- Bootstrap Dropdown selection是在*all*下拉菜单上设置选择
- 以不同的顺序输出数据
- 重新排列HTML元素的顺序并更改内容
- 当一些承诺失败时,如何继续使用$q.all()
- 在Javascript中列出顺序子集元素
- 是否“;对于的“;循环迭代遵循JavaScript中的数组顺序
- Mongodb$in以与数组中相同的顺序获取结果
- Promise.all:解析值的顺序
- Promise.all()没有按照预期的顺序解析承诺
- Promise的调度顺序.然后在Promise.all中分组
- 是 Node.js原生 Promise.all 并行或顺序处理