有没有办法克服 Node.js 中的回调 if(err) 样板文件?

Is there a way to overcome the callback if(err) boilerplate in Node.js?

随着项目的发展,我们开始在几乎所有地方都使用这种非常受欢迎的防御性代码片段:

func(err, result){
   if(err){

      console.log('An error occurred!, @myModule :' + err);
      return callback(err);
    }

    //then the rest.. 
}

快速 google 搜索揭示了一些试图克服这一普遍问题的库,例如https://www.npmjs.com/package/callback-wrappers.

但是,在不损害我们拥有的早期错误处理机制的情况下,最大限度地减少样板代码的最佳方法是什么?

有几种方法可以帮助缓解这个问题,都使用外部模块。

首先,我的首选方法是使用 async, and in particular, async.series, async.parallel or async.waterfall。如果在任何异步调用中发生错误,这些方法中的每一个都将直接跳到最后一个函数,从而防止在整个回调过程中出现 if(err) 条件。

例如:

async.waterfall([
  function(cb) {
    someAsyncOperation(cb);
  },
  function(result, cb) {
    doSomethingAsyncWithResult(result, cb);
  }
], function(err, result) {
  if(err) {
    // Handle error - could have come from any of the above function blocks
  } else {
    // Do something with overall result
  }
});

另一种选择是使用 promise 库,例如 q。这有一个函数 Q.denodeify 可以帮助您将回调式代码包装成 promise 式。对于承诺,您使用 .then..catch.done:

var qSomeAsyncOperation = Q.denodeify(someAsyncOperation);
var qDoSomethingAsyncWithResult = Q.denodeify(doSomethingAsyncWithResult);

Q()
  .then(qSomeAsyncOperation)
  .then(qDoSomethingAsyncWithResult)
  .done(function(result) {
    // Do something with overall result
  }, function(err) {
    // Handle error - could have come from any of the above function blocks
  });

我更喜欢使用 async,因为它更容易理解正在发生的事情,而且更接近 node.js 采用的真正的回调风格。