Javascript 使用ES6承诺的顺序迭代

Javascript 使用ES6承诺的顺序迭代,javascript,node.js,promise,es6-promise,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.forEa

我希望下面的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');
});
需要修改的内容,以便最后打印“已完成的所有任务”

  • 我的示例使用ES6承诺,而不是蓝鸟
  • 我也不是问一个关于承诺的一般性问题,而是问一个具体的例子

  • 在所有
    then
    函数中,您不会返回任何内容,而是触发一个异步操作。因此,承诺链与异步操作无关。这就是为什么你不能如你所愿控制流量的原因

    您可以做的是,从每个
    then
    处理程序返回一个承诺,只有在异步操作完成时才能解析,如下所示

      tasks.forEach(function(task) {
        promise = promise.then(function() {
          return new Promise((resolve, reject) => {
            setTimeout(function() {
              console.log(task);
              resolve();
            }, task);
          })
        });
      });
    
    '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,以此类推。基本上,您的程序将在大约10秒(1+2+3+4秒)后退出,因为我们正在按顺序执行所有异步函数


    但是如果你想让它们同时触发,那么就使用
    Promise.all
    ,如下所示

      tasks.forEach(function(task) {
        promise = promise.then(function() {
          return new Promise((resolve, reject) => {
            setTimeout(function() {
              console.log(task);
              resolve();
            }, task);
          })
        });
      });
    
    '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秒后完成所有异步操作,因为所有异步操作都会立即启动。

    目前,这是我找到的唯一一种方法,可以以顺序和分块方式迭代promise数组

    请检查代码示例

    const list = [1,2,3,4,5];
    
    数字越高,承诺得到解决的速度就越快

    const functionWithPromise = item => { 
      return new Promise((resolve) =>{
        setTimeout(resolve, 6000 - (1000 * item ) , item);
    })}
    
    all返回一个包含承诺的数组

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

    嵌套回调不是
    解析的承诺。修改匿名函数以返回一个新的
    承诺
    ,该承诺在超时后解析。可能重复