首页 > 解决方案 > 使用 array.reduce 在没有 Promise 的情况下顺序触发异步函数

问题描述

我可以像这样一个接一个地执行异步函数:

function asyncFn(e, cb) {
  return new Promise((res, rej) => {
    setTimeout(() => {
      console.log(e);
      res();
    }, 1000);
  });
}

var arr = [1,2,3,4,5];
arr.reduce(
  (chain, e) => chain.then(()=>asyncFn(e)),
  Promise.resolve()
);

是否可以使用回调而不是解决承诺来做同样的事情?

标签: javascriptnode.jsasynchronouses6-promise

解决方案


当然可以,但它有点复杂:

const logLater = (msg, time, cb) => setTimeout(() => (console.log(msg), cb()), time);

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

arr.reduceRight((next, el) => () => logLater(el, 1000, next), () => console.log("all done!"))();

或多行:/:

function logLater(msg, time, cb) {
 setTimeout(function() {
   console.log(msg);
   cb();
 }, time);
}

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

arr.reduceRight(function(next, el) {
 return function current() {
   logLater(el, 1000, next);
 };
}, function() { })();

建立回调链是向后的,因此记录5将被包装在一个函数中,该函数在调用时记录它,然后将该函数传递到包装器中,该包装器将在记录4时调用它,该包装器传递给包装器等等。44next3


但是,如果您只想对数组的所有元素执行某个任务并等待上一个回调,则可以使用调用自身的函数来执行此操作:

function logLater(msg, time, cb) {
 setTimeout(function() {
   console.log(msg);
   cb();
 }, time);
}

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

(function  next(i) {
   logLater(arr[i], 1000, function done() {
     if(i < arr.length - 1) next(i + 1);
   });
})(0);

推荐阅读