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

Dan*_*unu 8 javascript asynchronous node.js

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

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

00d*_*ani 11

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

相比之下,Promise在我看来是异步代码问题的更通用的解决方案.它们不仅乍一看提供了明显的好处 - 错误冒泡和扁平回调金字塔,否则需要各种复杂模式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);
    });
Run Code Online (Sandbox Code Playgroud)

async.waterfall在大多数promise库中没有等价物(或者至少在Q中没有一个),因为从头开始实现它是如此简单Array.reduce,就像这样(基于Q的例子,但在其他promise库上几乎相同):

[
  function() {
    return asyncCall('argument');
  },
  function(resultOfFirstCall) {
    return anotherCall(resultOfFirstCall, 'someOtherArgument');
  }
].reduce(Q.when, Q())
 .then(useFinalResult, handle);
Run Code Online (Sandbox Code Playgroud)

其他重要功能async包括async.parallel,其中Q包括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);
Run Code Online (Sandbox Code Playgroud)

并且async.map.当你使用promises时实际上并不需要 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);
Run Code Online (Sandbox Code Playgroud)

其余部分async同样易于使用您的promise库中相对简单的部分简洁地实现.(请注意,最后一个示例使用了一个函数Q.nfbind:Q提供nfbind的其他nf*函数基本上只需要使用带有nodeback API的promises,因此甚至没有特别大的阻抗试图将promises用于期望节点回送的库.)

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

回调是必要的,承诺功能是值得阅读的更多信息在这一般情况下.


And*_*ard 3

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

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