在javascript中,使用回调执行多个异步函数的最佳实践是什么?

in javascript, what are best practices for executing multiple asynchronous functions with callback?

本文关键字:函数 异步 最佳 是什么 javascript 执行 回调      更新时间:2023-09-26

有一个函数需要调用不确定数量的其他(可能是异步的)函数,每个函数都有回调,我使用以下模式:

虽然很确定这是正确的,但在美学上不是很令人愉快。

<>之前//负责计算和调用aysnc函数函数fn(arg, outNext) {//计算将调用多少个函数var waitCt = 0;Var a, b, c;if(a = arg['a']);if(b = arg['b']);if(c = arg['c']);//调用函数(a)任意的;a, inNext);if(b) fnRandom(arg, inNext);if(c) fnClueless(15, inNext);//回调函数函数inNext(err) {//等待少一个函数waitCt——;//如果找到,返回errif(err) outNext(err);//如果所有函数都执行,则返回nullif(wait == 0) outNext();//否则等待其他函数完成返回;}}之前

对我来说似乎有必要采取两步:第一步查看将调用多少函数,第二步执行调用。但也许是我的大脑被老派的编程弄糊涂了,或者昨晚看了太多的李尔王。

我所见过的针对多个aysnc函数的最佳管理思想是在Script Junkie的文章中描述的deferred和Futures,这篇关于FutureJS实现的文章,这篇msdn的文章和这个Stack Overflow问题。

这实际上是一种结构化的方式来考虑多个异步调用的排序或定义它们之间的执行依赖关系,它似乎对不同框架正在进行的多个实现(已经可用)有吸引力,因此它似乎是一个普遍支持的想法,无论现在还是将来都将对学习有用。

管理多个具有依赖关系的异步调用,手工操作确实很麻烦。代码不仅看起来很乱,而且无法阅读,甚至无法使用调试器。调试通常需要将大量信息转储到日志文件中,然后尝试找出发生了什么。如果涉及到时间,那么你真的陷入了困境。在我的上一个项目中,我仍然有一个未解决的bug的唯一领域是在启动时四个不同的异步调用之间错过了某种依赖关系。我已经加强了代码,使其几乎不会发生错误,但它还没有完全消失。下一步是切换到使用deferred,并添加一些正式的结构。

对于一些更大的库,我们有jQuery的Deferred, YUI3有Async Queue(它没有一般的Deferred那么强大,但是很有用),Dojo有一个Deferred对象,还有一些没有绑定到主库的Deferred库。

我有一个after效用函数。

var after = function _after(count, f) {
  var c = 0, results = [];
  return function _callback() {
    switch (arguments.length) {
      case 0: results.push(null); break;
      case 1: results.push(arguments[0]); break;
      default: results.push(Array.prototype.slice.call(arguments)); break;
    }
    if (++c === count) {
      f.apply(this, results);
    }
  };
};
// fn responsible for figuring out and calling aysnc funcs
function fn( arg, outNext ) {
    var cb = after(Object.keys(arg).length, function(data) {
      // all finished. Do something
    });
    // replace fa, fb, fc with f['a'], f['b'], f['c']
    Object.keys(arg).forEach(function(k) { f[k](arg[k], cb); });
}

这应该用于简单的情况。对于更复杂的情况,使用某种形式的流控制,如Futures