Promise.all:已解析值的顺序

2020/10/18 06:21 · javascript ·  · 0评论

查看MDN看起来像values传递给then()Promise回调。all包含按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(即支持该Iterator接口的对象)作为参数,然后再调用PerformPromiseAll( iterator, constructor, resultCapability)它,后者iterable使用循环IteratorStep(iterator)

这意味着,如果
Promise.all()严格要求您传递给的可迭代对象,则一旦传递它们仍将对其进行订购。

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


所有这一切意味着,只要严格地对输入进行排序(例如,数组),就可以严格地将输出作为输入进行排序。

您可以在下面的小提琴(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使用与原始Promises的输入顺序相对应的数组来聚合所有已解析的值(请参阅聚合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.logPromises语句按以下顺序显示的原因

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

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

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

如果您还想保证Promises的实际执行,那么您需要一个Promise队列之类的概念。这是使用p-queue的示例(请注意,您需要将所有Promises包装在函数中):

顺序承诺队列

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

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

本文地址:http://javascript.askforanswer.com/promise-allyijiexizhideshunxu.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!