var callback = function(err,data) { if (err) { /* do something if there was an error */ } /* other logic here */ };
var callback = function(data) { if (isError(data)) { /* do something if there was an error */ } /* other logic here */ };
似乎更简单.我能看到的唯一缺点是函数不能将错误作为实际预期的返回值返回 – 但我相信这是一个非常微不足道的用例.
为什么错误优先模式被认为是标准的?
编辑:isError的实现:
var isError = function(obj) { try { return obj instanceof Error; } catch(e) {} return false; };
解决方法
这只是一个惯例. Node也可以使用你建议的约定 – 除了你不会将错误对象作为成功的预期值返回时,根据你的特殊要求,这可能是也可能不是问题.
具有当前Node约定的事情是有时回调可能不期望任何数据,并且错误是它们采用的唯一参数,并且有时函数期望成功的多个值 – 例如,参见
request(url,(err,res,data) => { if (err) { // you have error } else { // you have both res and data } });
有关上述代码的完整示例,请参阅this answer.
但即使在具有多个参数的函数中,您也可以将第一个参数设置为错误,即使这样,我也不会发现您的样式存在任何问题.
错误优先的节点式回调是Ryan Dahl最初使用的,它现在非常通用,并且可用于任何采用回调的异步函数.并不是说这个约定比你的建议更好或更糟,但是有一个约定 – 无论它是什么 – 使得回调和回调的组合成为可能,而像async这样的模块依赖于它.
实际上,我看到了一种方法,你的想法优于传统的Node约定 – 不可能用错误和定义的第一个非错误参数调用回调,这对于Node样式的回调是可能的,有时可能发生.这两个约定都可能有两次调用回调 – 这是一个问题.
但是在JavaScript中还有另一个广泛使用的约定,特别是Node,其中不可能同时定义错误和数据,另外不可能两次调用回调 – 而不是回调你返回一个promise而不是显式检查错误值如果在节点样式回调或样式回调中的情况下,您可以单独添加仅获取相关数据的成功和失败回调.
所有这些风格在他们能做的事情上非常相同:
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 });
Promise可能更方便您的需求,并且已经广泛支持使用它们的许多工具,如Bluebird和其他.
您可以看到其他一些答案,其中我解释了回调和承诺之间的区别以及如何更详细地使用它们,这在这种情况下可能对您有所帮助:
> A detailed explanation on how to use callbacks and promises
> Explanation on how to use promises in complex request handlers
> An explanation of what a promise really is,on the example of AJAX requests
> Examples of mixing callbacks with promises
当然,我认为你没有理由不能编写一个将Node风格的回调转换为你的样式回调的模块,反之亦然,而且承诺也是如此,就像promisify和asCallback在Bluebird中工作一样.如果使用您的回调样式对您来说更方便的话,这似乎是可行的.
更新
我刚刚在npm上发布了一个模块,您可以使用它来获得您首选的回调样式:
> https://www.npmjs.com/package/errc
您可以安装它并在项目中使用:
npm install errc --save
它允许你有这样的代码:
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));
有关更多示例,请参阅
> https://github.com/rsp/node-errc-example
我编写这个模块作为如何操作函数和回调以满足您的需求的示例,但我在MIT许可下发布并在npm上发布,因此您可以在实际项目中使用它,如果您愿意.
这展示了Node的灵活性,其回调模型以及编写高阶函数以创建适合您需求的自己的API的可能性.我发布它希望它可以作为一个例子来理解Node回调样式.