【问题标题】:npm's guidelines on callback errorsnpm 关于回调错误的指南
【发布时间】:2015-08-13 00:50:27
【问题描述】:

我在阅读npm’s coding style guidelines 时发现了以下非常神秘的建议:

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

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

这是我使用 async 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
  }
})

【问题讨论】:

    标签: javascript asynchronous error-handling callback npm


    【解决方案1】:

    是的,这会导致无限循环。但是,他们不是在谈论那种类型的回调。相反,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
        }
    }
    

    【讨论】:

    • @chharvey 我没有重新定义fs.readdir。我只是借用了您的代码块并将其包装在一个模块中。 yourLibrary 可以是你想要的任何东西,例如,一种计算第 n 个斐波那契数的方法。您希望其他人能够在导入您的模块后使用yourLibrary.functionName(param1, callback)
    • 是的,我的错。我一添加评论就意识到了这一点。尽管如此,为什么getDirectoryFiles 函数包含fs.readdir 仍然令人困惑。我不知道堆栈的顺序是什么。
    【解决方案2】:

    他们想说的是你应该设计你的模块,以便异步函数不会抛出错误来捕获,而是在回调内部处理(就像你提供的 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,这只是您必须采取的额外步骤,它可以在回调内部轻松处理(如果您正在异步设计它,您应该这样做)。

    【讨论】:

      猜你喜欢
      • 2021-06-05
      • 2020-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-29
      • 2013-01-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多