Node.js 为什么节点更喜欢错误优先回调?
节点程序员通常使用如下范例:Node.js 为什么节点更喜欢错误优先回调?,node.js,callback,Node.js,Callback,节点程序员通常使用如下范例: let callback = function(err, data) { if (err) { /* do something if there was an error */ } /* other logic here */ }; var errc = require('errc'); var fs = require('fs'); var isError = function(obj) { try { return obj instanceof
let callback = function(err, data) {
if (err) { /* do something if there was an error */ }
/* other logic here */
};
var errc = require('errc');
var fs = require('fs');
var isError = function(obj) {
try { return obj instanceof Error; } catch(e) {}
return false;
};
var callback = function(data) {
if (isError(data)) {
console.log('Error:', data.message);
} else {
console.log('Success:', data);
}
};
fs.readFile('example.txt', errc(callback));
为什么不将函数简化为只接受一个参数,即错误或响应
let callback = function(data) {
if (isError(data)) { /* do something if there was an error */ }
/* other logic here */
};
似乎更简单。我能看到的唯一缺点是函数不能将错误作为实际的预期返回值返回——但我相信这是一个极其微不足道的用例
为什么错误优先模式被视为标准模式
编辑:iError的实现
let isError = obj => obj != null && obj instanceof Error;
另一个编辑:我的替代方法是否可能比节点约定更方便,因为只接受一个参数的回调更有可能被非回调用例重用?因为没有这个约定,开发人员将不得不维护不同的签名和API,不知道将错误放在arguments数组的何处 在大多数情况下,可能有许多参数,但只有一个错误-并且您知道在哪里可以找到它 Joyent甚至在他们参与更多的时候: 回调是传递事件的最基本方式 异步的。用户向您传递一个函数(回调),然后 稍后异步操作完成时调用它。 通常的模式是调用回调作为回调(err, 结果),其中err和result中只有一个非空,具体取决于 操作是否成功 (请参阅下面的“更新”,了解npm模块如何使用问题中的回调约定。) 这只是一个惯例。Node也可以使用您建议的约定,但您注意到在成功时不能将错误对象作为预期值返回,这可能是问题,也可能不是问题,具体取决于您的特定需求 当前节点约定的问题是,有时回调可能不需要任何数据,
err
是它们所采用的唯一参数,有时函数在成功时需要多个值—例如,请参阅
request(url, (err, res, data) => {
if (err) {
// you have error
} else {
// you have both res and data
}
});
有关上述代码的完整示例,请参见
但是,即使在使用多个参数的函数中,您也可以将第一个参数设置为错误,即使这样,我也看不出您的样式有任何问题
错误优先节点样式回调最初由Ryan Dahl使用,现在它非常通用,适用于任何接受回调的异步函数。并不是说这个约定比你建议的好或者更糟,而是有了一个约定-不管它是什么-使得回调和回调函数的组合成为可能,像这样的模块依赖于此
事实上,我看到您的想法优于经典节点约定的一种方式——不可能在同时定义了error和第一个non-error参数的情况下调用回调,这对于节点样式的回调是可能的,有时也会发生。不过,这两种约定都可能会调用回调两次,这是一个问题
但是JavaScript中还有另一个广泛使用的约定,尤其是Node,如果无法同时定义错误和数据,并且无法调用回调两次,则返回承诺,而不是像节点样式回调或样式回调那样在if
中显式检查错误值,您可以分别添加仅获取相关数据的成功和失败回调
所有这些样式在它们的功能上几乎相同:
nodeStyle(params, function (err, data) {
if (err) {
// error
} else {
// success
}
};
yourStyle(params, function (data) {
if (isError(data)) {
// error
} else {
// success
}
};
promiseStyle(params)
.then(function (data) {
// success
})
.catch(function (err) {
// error
});
承诺可能更方便满足您的需求,而且这些承诺已经得到了很多工具的广泛支持,例如和其他工具
您可以看到一些其他答案,其中我解释了回调和承诺之间的区别,以及如何更详细地一起使用,这可能对您在这种情况下有所帮助:
npm install errc --save
它允许您拥有如下代码:
let callback = function(err, data) {
if (err) { /* do something if there was an error */ }
/* other logic here */
};
var errc = require('errc');
var fs = require('fs');
var isError = function(obj) {
try { return obj instanceof Error; } catch(e) {}
return false;
};
var callback = function(data) {
if (isError(data)) {
console.log('Error:', data.message);
} else {
console.log('Success:', data);
}
};
fs.readFile('example.txt', errc(callback));
有关更多示例,请参见:
这展示了Node及其回调模型的灵活性,以及编写高阶函数以创建适合您需要的API的可能性。我发布它的目的是希望它可以作为理解节点回调样式的一个示例。您打算如何可靠地检查
iError
中的错误?编辑为包含iError
实现!谢谢aring,尽管我完全理解错误优先回调的用法!我只是对这样一种格式是如何成为广为接受的惯例感兴趣。@GershomMaes,回答关于你的方法的问题:在我看来,你的方法至少慢了一些。很好的回答,很多有用的附加信息!