Javascript 以非阻塞顺序循环异步回调

Javascript 以非阻塞顺序循环异步回调,javascript,loops,nonblocking,Javascript,Loops,Nonblocking,在这里碰壁试图让它工作-控制台.log的输出应该是0,1,2,3。它基本上应该在数组中循环,并以非阻塞方式按顺序调用函数(如果传入,则等待done()): 我不介意解决方案是否使用生成器、承诺或其他东西。我在想,这个函数可以按照以下方式进行包装: function fnWrapper(fn) { return new Promise(function(resolve) { if (fn.length >= 1) { // If the done callback i

在这里碰壁试图让它工作-控制台.log的输出应该是
0,1,2,3
。它基本上应该在数组中循环,并以非阻塞方式按顺序调用函数(如果传入,则等待
done()
):

我不介意解决方案是否使用生成器、承诺或其他东西。我在想,这个函数可以按照以下方式进行包装:

function fnWrapper(fn) {
  return new Promise(function(resolve) {
    if (fn.length >= 1) {
      // If the done callback is passed in.
      fn(resolve);
    } else {
      fn();
      resolve();
    }
  });
}

array.reduce((promise, fn) => promise.then(fnWrapper(fn)), Promise.resolve());

但到目前为止,我试图用生成器或promise/reduce循环完成这一过程的尝试是非常失败的。有什么想法吗?谢谢


更新:PS我无法控制在

中调用
done()
将使用什么异步方法这里有一个使用promises(和
Array.prototype.reduce
以串联运行函数)的解决方案:


我意识到,为了让我的承诺按顺序执行,我需要返回一个函数,该函数在
中返回承诺,然后在
中返回承诺(而不是将承诺本身传递给它):


Codepen:

这是一个很好的解决方案,谢谢,问题是这些函数是由用户编写的,我无法控制他们使用的异步方法。异步方法是否应该是一致的?您最好选择一种方法,并向用户解释您的API需要哪种异步方法。是的,您可能是对的,如果我想不出什么,我会考虑一下并接受。您也可以尝试包装用户函数以创建一致的API。下面是我尝试的一个包装函数,它可以处理最后一个参数回调函数或承诺返回函数:是的,我基本上是在尝试这样做,但实际上你已经开始工作了,我明天会阅读并接受-谢谢你的帮助
function fnWrapper(fn) {
  return new Promise(function(resolve) {
    if (fn.length >= 1) {
      // If the done callback is passed in.
      fn(resolve);
    } else {
      fn();
      resolve();
    }
  });
}

array.reduce((promise, fn) => promise.then(fnWrapper(fn)), Promise.resolve());
// promise version of setTimeout
function delay(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

var array = [
  function() {
    return delay(2000)
      .then(() => console.log(0));
  },

  function() {
    return delay(200)
      .then(() => console.log(1));
  },

  function() {
    console.log(2);
  },

  function() {
    return delay(70)
      .then(() => console.log(3));
  }
];

array.reduce((promise, fn) => promise.then(fn), Promise.resolve());
function fnWrapper(fn) {
  return new Promise(function(resolve) {
    if (fn.length >= 1) {
      // If the done callback is passed in.
      fn(resolve);
    } else {
      fn();
      resolve();
    }
  });
}

array.reduce((promise, fn) => promise.then(() => fnWrapper(fn)), Promise.resolve());