简体   繁体   English

Promise.all:已解析值的顺序

[英]Promise.all: Order of resolved values

Looking at MDN it looks like the values passed to the then() callback of Promise.all contains the values in the order of the promises.看着MDN它看起来像values传递给then() Promise.all的回调包含了承诺的顺序值。 For example:例如:

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?
});

Can anybody quote a spec stating in which order values should be in?任何人都可以引用说明values应该按哪个顺序排列的规范吗?

PS: Running code like that showed that this seems to be true although that is of course no proof - it could have been coincidence. PS:运行这样的代码表明这似乎是真的,尽管这当然没有证据 - 这可能是巧合。

Shortly, the order is preserved .很快, 订单就被保留了下来

Following the spec you linked to, Promise.all(iterable) takes an iterable as a parameter and internally calls PerformPromiseAll(iterator, constructor, resultCapability) with it, where the latter loops over iterable using IteratorStep(iterator) .按照您链接的规范, Promise.all(iterable)将一个iterable作为参数并在内部使用它调用PerformPromiseAll(iterator, constructor, resultCapability) ,后者使用IteratorStep(iterator)循环遍历iterable IteratorStep(iterator)

Resolving is implemented via Promise.all() Resolve where each resolved promise has an internal [[Index]] slot, which marks the index of the promise in the original input.解析是通过Promise.all() Resolve ,其中每个解析的 promise 都有一个内部的[[Index]]槽,它标记了原始输入中 promise 的索引。


All this means the output is strictly ordered given the iterable you pass to Promise.all() is strictly ordered (for example, an array).所有这一切都意味着输出是严格排序的,因为您传递给 Promise.all() 的迭代是严格排序的(例如,一个数组)。

You can see this in action in the below fiddle (ES6):您可以在下面的小提琴(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)); });

As the previous answers have already stated, Promise.all aggregates all resolved values with an array corresponding to the input order of the original Promises (see Aggregating Promises ).正如前面的答案已经说明的那样, Promise.all将所有已解析的值与与Promise.all的输入顺序相对应的数组聚合(请参阅聚合 Promises )。

However, I would like to point out, that the order is only preserved on the client side!但是,我想指出的是,该订单仅保留在客户端!

To the developer it looks like the Promises were fulfilled in order but in reality, the Promises are processed at different speeds.对开发人员来说,看起来 Promises 是按顺序完成的,但实际上,Promises 以不同的速度处理。 This is important to know when you work with a remote backend because the backend might receive your Promises in a different order.当您使用远程后端时,了解这一点很重要,因为后端可能会以不同的顺序接收您的 Promise。

Here is an example that demonstrates the issue by using timeouts:以下是通过使用超时来演示该问题的示例:

Promise.all承诺.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)

In the code shown above, three Promises (A, B, C) are given to Promise.all .在上面显示的代码中,三个 Promises (A, B, C) 被赋予了Promise.all The three Promises execute at different speeds (C being the fastest and B being the slowest).这三个 Promise 以不同的速度执行(C 最快,B 最慢)。 That's why the console.log statements of the Promises show up in this order:这就是console.log语句按以下顺序显示的原因:

C (fast) 
A (slow)
B (slower)

If the Promises are AJAX calls, then a remote backend will receive these values in this order.如果 Promise 是 AJAX 调用,则远程后端将按此顺序接收这些值。 But on the client side Promise.all ensures that the results are ordered according to the original positions of the myPromises array.但是在客户端Promise.all确保根据myPromises数组的原始位置对结果进行排序。 That's why the final result is:这就是为什么最终结果是:

['A (slow)', 'B (slower)', 'C (fast)']

If you want to guarantee also the actual execution of your Promises, then you would need a concept like a Promise queue.如果您还想保证 Promise 的实际执行,那么您将需要一个类似 Promise 队列的概念。 Here is an example using p-queue (be careful, you need to wrap all Promises in functions):下面是一个使用p-queue的例子(注意,你需要将所有的 Promise 包装在函数中):

Sequential Promise Queue顺序承诺队列

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);

Result结果

A (slow)
B (slower)
C (fast)

['A (slow)', 'B (slower)', 'C (fast)']

Yes, the values in results are in the same order as the promises .是的, results中的值与promises顺序相同。

One might cite the ES6 spec on Promise.all , though it's a bit convoluted due to the used iterator api and generic promise constructor.人们可能会 Promise.all引用ES6 规范,但由于使用了迭代器 api 和通用的 promise 构造函数,这有点令人费解。 However, you'll notice that each resolver callback has an [[index]] attribute which is created in the promise-array iteration and used for setting the values on the result array.但是,您会注意到每个解析器回调都有一个[[index]]属性,该属性是在 promise-array 迭代中创建的,用于设置结果数组上的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM