Node.js 如何在节点中执行此操作?

Node.js 如何在节点中执行此操作?,node.js,asynchronous,flow-control,Node.js,Asynchronous,Flow Control,我有一个任务,如果已经完成,我需要跳过它,如果没有,我需要执行它。任务是异步的。在此之后,我需要对另一个任务执行相同的检查,并可能执行它 if(!taskStatus.complete[x]) asyncTasks[x](function(result){ if(!taskStatus.complete[y]) asyncTasks[y](function(result){ stow(result); }); }); if(!taskSta

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

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的时髦是不可避免的吗?淋巴结太过干燥了吗?

你应该把它变成承诺(这里是一个例子)。它们允许您优雅地表示代码的异步函数之间的依赖关系

如果您将函数转换为使用承诺,下面是一个特定用例的示例:

getSomeX()
.then(getSomeY)
.then(function(result) {
    stow(result);
})
这很好地表明您只想在Y完成时调用
stow()
,并且Y需要先调用X

下面是一个示例(以及相应的使用延迟的小节),介绍如何将函数转换为使用承诺:

var Q = require('q');
var getSomeX = function() {
    var deferred = Q.deferred();
    asyncTasks[x](function (result) {
        deferred.resolve(result);
    });
    return deferred.promise;
}
编辑:您还可以使用Q的功能,通过
denodeify
函数自动转换异步函数,该函数尊重节点的常规回调样式(err,result):

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

看一看请不要使用延迟,代码是浪费空间和错误,因为您需要手动传播所有类型的错误,这有点违背了首先使用承诺的意义。相反,如果某些api使用回调约定,您可以通过使用promise库的
denodeify/promisify
函数将其转换为promise api。在bluebird中,需要3行代码才能将节点mysql和redis转化为健壮的promise API,就好像它们最初就是为此而设计的一样。对于这些库中的每个函数,手动使用延迟将花费数千行。我在答案中添加了一个小的
denodeify
示例。我一开始没有提到它,因为OP的异步函数不尊重标准节点异步样式:它们不返回(err,res)。但这确实是一个公平的观点。