关于回调错误的npm指南

时间:2015-05-30 02:44:30

标签: javascript asynchronous error-handling callback npm

我正在阅读npm’s coding style guidelines并且遇到了以下非常神秘的建议:

  

要小心,永远不要扔任何东西。它比没用更糟糕。只需将错误消息作为回调的第一个参数发回。

它们究竟是什么意思?如何实现这种行为?他们建议在自己内部调用回调函数吗?

这是我能想到的使用异步fs.readdir方法。

fs.readdir('./', function callback(err, files) {
  if (err) {
    // throw err  // npm says DO NOT do this!
    callback(err) // Wouldn’t this cause an infinite loop?
  }
  else {
    // normal stuff
  }
})

2 个答案:

答案 0 :(得分:6)

他们想说的是你应该设计你的模块,这样异步函数不会抛出错误来捕获,而是在回调中处理(比如你提供的fs.readdir示例) ...

所以,例如,这就是他们所说的你应该设计你的模块:

var example = {
    logString: function(data, callback){
      var err = null;
      if (typeof data === "string") {
        console.log(data);
      } else {
        err = {"message": "Data is not a string!"};
      }
      callback(err);
    }
}

他们希望您设计它,以便最终用户可以处理回调内部的错误,而不是使用try / catch语句...例如,当我们使用example对象时:

example.logString(123, function(err){
  // Error is handled in callback instead of try/catch
  if (err) console.log(err)
});

这会记录{"message": "Data is not a string!"},因为数据的typeof不等于"string"

以下是他们应该避免的一个例子:

当您使用异步回调时,他们不希望您抛出错误......所以我们说我们重新设计了模块,因此logString方法会抛出错误而不是将其传递给回调。 ..像这样:

var example = {
    logString: function(data, callback){
      if (typeof data === "string") {
        console.log(data);
      } else {
        // See, we're throwing it instead...
        throw {"message": "Data is not a string!"};
      }
      callback();
    }
}

有了这个,我们必须完成整个try / catch语句,否则你会得到一个未被捕获的错误:

try {
  example.logString(321, function(){
    console.log("Done!")
  });
} catch (e) {
  console.log(e)
}

最后的想法/摘要:

我认为NPM建议这种方法的原因是因为它在异步方法中更易于管理。

NodeJS和JavaScript一般都喜欢拥有一个异步环境,以便将它们整合到一个地方,错误处理等等。

使用try / catch,它只需要一个额外的步骤,当它可以在回调中轻松处理时(如果你是异步设计它,你应该这样做)。

答案 1 :(得分:2)

是的,这会导致无限循环。但是,他们并没有谈论这种类型的回调。相反,npm引用了用于与模块交互的回调。

扩展你的例子:

module.exports = {
    getDirectoryFiles: function (directory, done) {
        fs.readdir(directory, function callback(err, files) {
            if (err) {
                return done(err);
            } else {
                return done(null, files);
            }
        })
    }
}

您应该将err传递给上述范围内的回调,而不是传递给您当前正在处理的函数(在上述情况下为callback)。命名这些函数的唯一原因是帮助调试。

他们不说throw err的原因是因为节点使用了错误优先回调。每个人都希望你的库(如果它使用回调)将其错误作为第一个参数传播给回调。例如:

var yourLibrary = require("yourLibrary");

yourLibrary.getDirectoryFiles("./", function (err, files) {
    if (err) {
        console.log(err);
        // do something
    } else {
        // continue
    }
}