Javascript Promise.all:已解析值的顺序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28066429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 01:10:31  来源:igfitidea点击:

Promise.all: Order of resolved values

javascriptpromisees6-promise

提问by Thorben Croisé

Looking at MDNit looks like the valuespassed to the then()callback of Promise.all contains the values in the order of the promises. For example:

查看MDN,它看起来像values传递给then()Promise.all的回调包含按照承诺顺序的值。例如:

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 valuesshould 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:运行这样的代码表明这似乎是真的,尽管这当然没有证据 - 这可能是巧合。

回答by Nit

Shortly, the order is preserved.

很快,订单就被保留了下来

Following the spec you linked to, Promise.all(iterable)takes an iterable(that is, an object that supports the Iteratorinterface) as a parameter and later on calls PerformPromiseAll( iterator, constructor, resultCapability)with it, where the latter loops over iterableusing IteratorStep(iterator).
This means that if if the iterable you pass in to Promise.all()is strictly ordered, they will still be ordered once passed in.

按照您链接的规范,Promise.all(iterable)将一个iterable(即支持Iterator接口的对象)作为参数,然后在调用PerformPromiseAll( iterator, constructor, resultCapability)它时使用它,后者iterable使用IteratorStep(iterator).
这意味着如果您传入的可迭代对象Promise.all()是严格排序的,则它们在传入后仍将被排序。

Resolving is implemented via Promise.all() Resolvewhere each resolved promise has an internal [[Index]]slot, which marks the index of the promise in the original input.

解析是通过Promise.all() Resolve每个解析的承诺都有一个内部[[Index]]插槽来实现的,它标记了原始输入中承诺的索引。



All this means that the output is strictly ordered as the input as long as the input is strictly ordered (for example, an array).

所有这一切意味着,只要输入是严格排序的(例如,数组),输出就会严格排序为输入。

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

回答by Benny Neugebauer

As the previous answers have already stated, Promise.allaggregates all resolved values with an array corresponding to the input order of the original Promises (see Aggregating Promises).

正如前面的答案已经说明的那样,Promise.all将所有已解析的值与与原始 Promise 的输入顺序相对应的数组聚合(请参阅聚合 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. This is important to know when you work with a remote backend because the backend might receive your Promises in a different order.

对开发人员来说,看起来 Promises 是按顺序完成的,但实际上,Promises 以不同的速度处理。当您使用远程后端时,了解这一点很重要,因为后端可能会以不同的顺序接收您的 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. The three Promises execute at different speeds (C being the fastest and B being the slowest). That's why the console.logstatements of the Promises show up in this order:

在上面显示的代码中,三个承诺(A、B、C)被赋予了Promise.all。这三个 Promise 以不同的速度执行(C 最快,B 最慢)。这就是 Promise 的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. But on the client side Promise.allensures that the results are ordered according to the original positions of the myPromisesarray. That's why the final result is:

如果 Promise 是 AJAX 调用,则远程后端将按此顺序接收这些值。但是在客户端Promise.all确保根据myPromises数组的原始位置对结果进行排序。这就是为什么最终结果是:

['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. Here is an example using p-queue(be careful, you need to wrap all Promises in functions):

如果您还想保证 Promise 的实际执行,那么您将需要一个类似 Promise 队列的概念。下面是一个使用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)']

回答by Bergi

Yes, the values in resultsare in the same order as the promises.

是的,中的值resultspromises.

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. 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.

人们可能会在 上引用ES6 规范Promise.all,但由于使用了迭代器 api 和通用的 promise 构造函数,这有点令人费解。但是,您会注意到每个解析器回调都有一个[[index]]在 promise-array 迭代中创建的属性,用于设置结果数组上的值。