使用ES6承诺的顺序迭代

时间:2016-06-20 06:42:07

标签: javascript node.js promise es6-promise

我原以为node.js下面的代码会按以下顺序打印输出

1000
2000
3000
4000
"All tasks completed"

相反,它是以下面提到的顺序打印

"All tasks completed"
1000
2000
3000
4000

代码

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

需要修改什么以便"所有任务完成"将在最后打印。

  1. 我的例子使用ES6承诺而不是蓝鸟。
  2. 此外,我不是在问一个关于承诺的一般性问题,而是一个具体的例子。

2 个答案:

答案 0 :(得分:4)

在所有then函数中,您没有返回任何内容,而是触发异步操作。因此,promise链与异步操作无关。这就是为什么你无法按照自己的意愿控制流量的原因。

你可以做的是,从每个then处理程序返回一个Promise,只有当异步操作完成时才会解析,就像这样

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

请记住,这将逐个触发异步操作。例如,一秒钟后,它将打印1000,第二个异步操作将开始,等待两秒,然后打印2000,依此类推。基本上,程序将在大约10秒(1 + 2 + 3 + 4秒)后退出,因为我们正在顺序执行所有异步功能。

但是如果你想让它们全部触发,那就使用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');
});

现在,所有异步功能都会立即触发,因此一秒钟后会打印1000,打印两秒后将打印2000,依此类推。您的程序将在4秒后完成所有异步操作,因为所有异步操作都会立即启动。

答案 1 :(得分:0)

当前,这是我发现的唯一一种以顺序AND阻塞方式遍历promise数组的方法...

请检查代码示例...

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

数字越大,承诺兑现的速度越快

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

Promise.all返回一个带有promises的数组

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

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

};

开始连锁

getData().then(console.log);