【问题标题】:How is one to do this in node?如何在节点中做到这一点?
【发布时间】:2013-11-16 13:53:38
【问题描述】:

我有一个任务,如果已经完成,我需要跳过它,如果还没有,我需要执行它。任务是异步的。在此之后,我需要对另一个任务进行相同的检查,并可能执行它...

if(!taskStatus.complete[x])
  asyncTasks[x](function(result){
    if(!taskStatus.complete[y])
      asyncTasks[y](function(result){
        stow(result);
      });
  });
if(!taskStatus.complete[y])
  asyncTasks[y](function(result){
    stow(result);
  });

也就是说,无论第一个任务是否完成,都需要执行第二个任务,但是如果要完成第一个任务,则只有完成后才能执行第二个任务。

我的代码在这里重复了很多次,这通常是一件非常糟糕的事情。 Node的时髦是不是无法避免? Node 是不是太时髦而不能 DRY?

【问题讨论】:

标签: node.js asynchronous flow-control


【解决方案1】:

你应该接受承诺(这里是good library that implements promises)。它们允许您优雅地表示代码的异步函数之间的依赖关系。

假设您将函数转换为使用 Promise,以下是您特定用例的示例:

getSomeX()
.then(getSomeY)
.then(function(result) {
    stow(result);
})

这很好地表明您只想在 Y 完成后调用 stow(),并且 Y 首先需要 X。

这是一个示例(以及相应的tutorial使用 Deferreds 小节),说明如何将函数转换为使用 Promise:

var Q = require('q');
var getSomeX = function() {
    var deferred = Q.deferred();
    asyncTasks[x](function (result) {
        deferred.resolve(result);
    });
    return deferred.promise;
}

编辑:您还可以使用 Q 的功能,通过 denodeify 函数自动转换尊重 Node 常用回调样式(错误、结果)的异步函数:

var getSomeX = Q.denodeify(asyncTasks[x]);

【讨论】:

  • 请不要使用延迟,代码浪费空间和错误,因为您需要手动传播所有错误类型,这有点违背了首先使用承诺的意义。相反,如果某些 api 使用回调约定,您可以使用您的 promise 库的 denodeify/promisify 函数轻松地将其转换为 promise API。在 bluebird 中,将 node-mysql 和 redis 转换为健壮的 Promise API 需要 3 行代码,就好像它们一开始就是为此而设计的一样。为这些库中的每个函数手动使用延迟会花费数千行。
  • 我在答案中添加了一个小的denodeify 示例。我一开始没有提到它,因为 OP 的异步函数不尊重标准的 Node 异步样式:它们不返回 (err, res)。但这确实是一个公平的观点。
猜你喜欢
  • 1970-01-01
  • 2014-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-12
  • 2020-10-26
相关资源
最近更新 更多