npm 关于回调错误的指南
npm's guidelines on callback errors
我通读了 npm’s coding style guidelines 并发现了以下非常神秘的建议:
Be very careful never to ever ever throw anything. It’s worse than useless. Just send the error message back as the first argument to the callback.
它们到底是什么意思,如何实现这一行为?他们是否建议在自身内部调用回调函数?
以下是我使用异步 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
}
})
是的,那会导致无限循环。然而,他们并不是在谈论那种类型的回调。相反,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
}
}
他们想说的是你应该设计你的模块,这样异步函数就不会抛出错误来捕获,而是在回调内部处理(就像在 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,这只是您必须采取的额外步骤,因为它可以在回调内部轻松处理(如果您正在异步设计它,您应该这样做)。
我通读了 npm’s coding style guidelines 并发现了以下非常神秘的建议:
Be very careful never to ever ever throw anything. It’s worse than useless. Just send the error message back as the first argument to the callback.
它们到底是什么意思,如何实现这一行为?他们是否建议在自身内部调用回调函数?
以下是我使用异步 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
}
})
是的,那会导致无限循环。然而,他们并不是在谈论那种类型的回调。相反,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
}
}
他们想说的是你应该设计你的模块,这样异步函数就不会抛出错误来捕获,而是在回调内部处理(就像在 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,这只是您必须采取的额外步骤,因为它可以在回调内部轻松处理(如果您正在异步设计它,您应该这样做)。