task.js生成器/承诺与异步回调

时间:2013-03-19 00:09:06

标签: javascript node.js asynchronous

我想知道在JavaScript中处理异步代码时哪两个方法更好。我想了解哪种方法可以实现更清晰的代码。我使用了promises,它们似乎比异步方法(https://github.com/caolan/async)更灵活。

我也知道Task.js库(http://taskjs.org/),但这依赖于yield关键字,它是Ecmascript Harmony的一部分。

4 个答案:

答案 0 :(得分:11)

async库封装了一些非常常见的异步模式,包括并行进行任意异步调用并异步迭代列表。它设计用于“nodeback”(err, res) API,这使得它对许多Node.js应用程序很有用。 async特定的解决方案,它只会简化库中包含的异步模式。

相比之下,承诺在我看来是异步代码问题的更多通用解决方案。它们不仅乍一看提供了明显的错误冒泡和扁平化回调金字塔的好处,而且需要各种复杂模式async封装的问题可以更简单地解决。

我将通过快速浏览一些async的可用模式来演示这一点。例如,async.waterfall函数的用法如下:

async.waterfall([
      function (cb) {
        asyncCall('argument', cb);
      },
      function(resultOfFirstCall, cb) {
        anotherCall(resultOfFirstCall, 'someOtherArgument' cb);
      },
    ], function(err, res) {
      if (err) handle(err);
      useFinalResult(res);
    });

在大多数promise库中没有等同于async.waterfall(或者至少Q中没有一个),因为这么简单使用{{1}从头开始实现它},就像这样(基于Q的示例,但在其他promise库上几乎相同):

Array.reduce

[ function() { return asyncCall('argument'); }, function(resultOfFirstCall) { return anotherCall(resultOfFirstCall, 'someOtherArgument'); } ].reduce(Q.when, Q()) .then(useFinalResult, handle); 中的其他重要功能包括async,其中Q包含为async.parallel

Q.all

// async async.parallel([ asyncFunc, asyncFunc2 ], function(err, res) { if (err) handle(err); useFinalResult(res); // res[0] === asyncFuncResult // res[1] === asyncFunc2Result }); // Q Q.all([ asyncFunc(), asyncFunc2() ]).then(useFinalResult, handle); 。当你使用promises时,你实际上不需要 async.map,因为正常async.map就足够了:

Array.map

// async async.map(['file', 'file2', 'file3'], fs.stat, function(err, res) { if (err) handle(err); useFinalResult(res); }); // Q Q.all(['file', 'file2', 'file3'] .map(Q.nfbind(fs.stat))) .then(useFinalResult, handle); 的其余部分同样易于使用您的promise库中相对简单的部分简洁地实现。 (注意,最后一个示例使用函数asyncQ.nfbind和Q提供的其他nfbind函数基本上只需要使用带有nodeback API的promises,因此甚至没有特别大的阻抗试图将promises用于期望节点返回的库。)

最后,您是否使用promises或nodebacks取决于您,但我认为promises是一种更加灵活,功能强大且通常简洁的方法来实现大多数异步操作。

Callbacks are imperative, promises are functional值得一读,以获取更多信息。

答案 1 :(得分:3)

由于您使用节点标记了您的问题,我建议使用异步库。控制流功能非常适合处理并消除丑陋且难以遵循的回调链。 API设置非常适合将遵循节点签名(error, result)的回调注入控制功能。它基本上包含在我编写的几乎所有节点脚本中。

虽然您也可以在客户端使用async,但对于大多数项目来说可能是不必要的。 jQuery包含promises,你可以用它们完成同样的事情。

答案 2 :(得分:1)

我认为promise / a和async lib具有差异目标,承诺专注于一步异步操作进度,异步专注于多步异步操作,对于节点,async对于大量异步apis使用更为狂野。

顺便说一句,要处理异步操作,使用命名函数代替匿名函数将是最有效的方法

答案 3 :(得分:0)

gumballhead推荐 async.js ,但如果你正在使用Node,那么 i 会建议使用Parse Cloud Code。他们的API与其他好东西(如数据库)一起构建了承诺。它节省了时间,您不必担心后端稳定性。您可以将module.exports稍加调整到exports包含任何NPM模块。它还与您的前端无缝集成!在我目前的项目中,我一直在使用这种方法取得成功,并且只想用新方法发表评论。

您可以使用Cloud Code,以及/何时/ 使用Cloud Code时,可以随意评论。因为我还没有这样的经历。

相关问题