简体   繁体   English

使用ES6的顺序迭代Promise

[英]Sequential iteration using ES6 promises

I was expecting that below node.js code will print output in following order 我期望在node.js下面的代码将按以下顺序打印输出

1000
2000
3000
4000
"All tasks completed"

Instead it is prints in below mentioned order 而是按以下提到的顺序打印

"All tasks completed"
1000
2000
3000
4000

The code 编码

'use strict';

var tasks = [1000, 2000, 3000, 4000];
var promise = Promise.resolve();


function test() {
  tasks.forEach(function(task) {
    promise = promise.then(function() {
      setTimeout(function() {
        console.log(task);
      }, task);
    });
  });
}

test();

promise.then(function() {
  console.log('All tasks completed');
});

What needs to be modified so that "All tasks completed" will be printed last. 需要修改什么,以便最后打印“所有任务已完成”。

  1. My example uses ES6 promises and not bluebird . 我的示例使用ES6 Promise,而不使用bluebird。
  2. Also I am not asking a general question about promises , rather it is about a specific example. 我也不是在问关于诺言的一般性问题,而是关于一个具体的例子。

In all your then functions you are not returning anything, but triggering an async operation. 在所有then函数中,您什么都不返回,而是触发异步操作。 So, the promise chain has nothing to do with the async operations. 因此,promise链与异步操作无关。 That is why you are not able to control the flow as you wished. 这就是为什么您无法按需要控制流量的原因。

What you could have done is, return a Promise from each of the then handlers, which will be resolved only when the async operation completes, like this 您可能要做的是,从每个then处理程序中返回一个Promise,仅当异步操作完成时才解决此问题,如下所示

  tasks.forEach(function(task) {
    promise = promise.then(function() {
      return new Promise((resolve, reject) => {
        setTimeout(function() {
          console.log(task);
          resolve();
        }, task);
      })
    });
  });

Remember, this will trigger the async operations one by one . 请记住, 这将一次触发异步操作 For example, after one second, it will print 1000 and the second async operation will be started which will wait for two seconds and then print 2000 and so on. 例如,一秒钟后,它将打印1000,第二个异步操作将开始,它将等待两秒钟,然后打印2000,依此类推。 Basically, you program will exit after approximately 10 seconds (1 + 2 + 3 + 4 seconds), as we are executing all the asynchronous functions sequentially. 基本上,您的程序将在大约10秒钟(1 + 2 + 3 + 4秒)后退出,因为我们将依次执行所有异步功能。


But if you wanted all of them to trigger at once , then use Promise.all , like this 但是, 如果您希望所有人都立即触发 ,请使用Promise.all ,就像这样

'use strict';

var tasks = [1000, 2000, 3000, 4000];

function test() {
  return Promise.all(tasks.map(function(task) {
    return new Promise((resolve, reject) => {
      setTimeout(function() {
        console.log(task);
        resolve();
      }, task);
    })
  }));
}

test().then(function() {
  console.log('All tasks completed');
});

Now, all the async functions are triggered at once, so after one second, 1000 will be printed, after two seconds 2000 will be printed and so on. 现在,所有异步功能都立即被触发,因此一秒钟后,将打印1000,两秒钟后将打印2000,依此类推。 Your program will complete all the async operations after 4 seconds, as all of them are started immediately. 您的程序将在4秒钟后完成所有异步操作,因为所有异步操作都会立即启动。

Currently, this is the only method I figured out to iterate over a promise array within a sequential AND blocking manner... 目前,这是我发现的唯一一种以顺序AND阻塞方式迭代promise数组的方法...

Please check the code example... 请检查代码示例...

const list = [1,2,3,4,5];

The higher the number the faster the promise gets resolved 数字越高,兑现承诺的速度越快

const functionWithPromise = item => { 
  return new Promise((resolve) =>{
    setTimeout(resolve, 6000 - (1000 * item ) , item);
})}

Promise.all returns an array with promises Promise.all返回带有promise的数组

const getData = async () => Promise.all(await iterateSequentiallyPromiseArray(list,functionWithPromise));

The for loop is the only loop that iterate in a blocking manner for循环是唯一以阻塞方式迭代的循环

const iterateSequentiallyPromiseArray = async (array, fn) => {
    try {
      const results = [];
      for (let i = 0; i < array.length; i++) { 
        console.log('Start with index: ', i);
        const r = await fn(array[i]);
        console.log('in promise iteration', r);
        results.push(r);
      }
      return results; // will be resolved value of promise
    } catch (err) {
      console.log('_processArray');
      throw err;
    }

};

Start the chain 开始连锁

getData().then(console.log);

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

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