为什么节点更喜欢错误优先回调? [英] Why does node prefer error-first callback?

查看:78
本文介绍了为什么节点更喜欢错误优先回调?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

节点程序员通常使用这样的范例:

Node programmers conventionally use a paradigm like this:

let callback = function(err, data) {
  if (err) { /* do something if there was an error */ }

  /* other logic here */
};

为什么不简化该函数以仅接受一个参数(它是错误或响应)?

Why not simplify the function to accept only a single parameter, which is either an error, or the response?

let callback = function(data) {
  if (isError(data)) { /* do something if there was an error */ }

  /* other logic here */  
};

似乎更简单.我唯一看到的缺点是函数不能将错误返回为它们的实际预期返回值-但我认为这是一个非常微不足道的用例.

Seems simpler. The only downside I can see is that functions can't return errors as their actual intended return value - but I believe that is an incredibly insignificant use-case.

为什么错误优先模式被认为是标准的?

Why is the error-first pattern considered standard?

isError的实现:

let isError = obj => obj != null && obj instanceof Error;

另一个我的替代方法是否可能比节点约定更方便,因为仅接受一个参数的回调也更有可能在非回调用例中重用?

ANOTHER Is it possible that my alternate method is somewhat more convenient than node convention, because callbacks which only accept one parameter are more likely to be reusable for non-callback use-cases as well?

推荐答案

(有关使用问题的回调约定的npm模块,请参见下面的更新".)

(See "Update" below for an npm module to use the callback convention from the question.)

这只是一个约定.节点也可以使用您建议的约定-除了您无法注意到的那样,成功后无法将错误对象作为预期值返回,这可能是问题也可能不是问题,具体取决于您的特定要求

This is just a convention. Node could use the convention that you suggest as well - with the exception that you wouldn't be able to return an error object as an intended value on success as you noticed, which may or may not be a problem, depending on your particular requirements.

当前Node约定的含义是,有时回调可能不期望任何数据,而err是它们采用的唯一参数,并且有时函数在成功时期望不止一个值-例如,参见

The thing with the current Node convention is that sometimes the callbacks may not expect any data and the err is the only parameter that they take, and sometimes the functions expect more than one value on success - for example see

request(url, (err, res, data) => {
  if (err) {
    // you have error
  } else {
    // you have both res and data
  }
});

有关完整示例,请参见此答案上面的代码.

See this answer for a full example of the above code.

但是,即使在使用多个参数的函数中,您也可能会使第一个参数成为错误,即使那样,您的样式也不会出现任何问题.

But you might as well make the first parameter to be an error even in functions that take more than one parameter, I don't see any issue with your style even then.

错误优先的Node风格的回调是Ryan Dahl最初使用的,现在已经非常普遍了,并且对于使用回调的任何异步函数都应如此.并不是说这个约定比您建议的更好或更糟,而是拥有约定-无论它是什么-使得回调和回调采用函数以及

The error-first Node-style callbacks is what was originally used by Ryan Dahl and it is now pretty universal and expected for any asynchronous functions that take callbacks. Not that this convention is better than what you suggest or worse, but having a convention - whatever it is - make the composition of callbacks and callback taking functions possible, and modules like async rely on that.

事实上,我看到了您的想法优于经典Node约定的一种方式-不可能同时调用带有错误和定义的第一个非错误参数的回调,这对于Node样式的回调是可能的,有时可以发生.两种约定都可能使回调函数被调用两次-这是一个问题.

In fact, I see one way in which your idea is superior to the classical Node convention - it's impossible to call the callback with both error and the first non-error argument defined, which is possible for Node style callbacks and sometimes can happen. Both conventions could potentially have the callback called twice though - which is a problem.

但是在JavaScript中,尤其是在Node中,还有另一种广泛使用的约定,即不可能同时定义错误和数据,而且不可能两次调用回调-而不是进行回调,而是返回promise,而不是像在Node样式回调或样式回调中一样,显式检查if中的错误值,您可以分别添加仅获取相关数据的成功和失败回调.

But there is another widely used convention in JavaScript in general and Node in particular, where it's impossible to define both error and data and additionally it's impossible to call the callback twice - instead of taking a callback you return a promise and instead of explicitly checking the error value in if as is the case in Node-style callbacks or your style callbacks, you can separately add success and failure callbacks that only get relevant data.

所有这些样式在功能上都差不多:

All of those styles are pretty much equivalent in what they can do:

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 和其他人.

Promises may be more convenient for your needs and those are already widely supported with a lot of tools to use them, like Bluebird and others.

您还可以看到其他一些答案,在这些地方我将解释回调和promise之间的区别以及如何更详细地使用它们,在这种情况下可能对您有帮助:

You can see some other answers where I explain the difference between callbacks and promises and how to use the together in more detail, which may be helpful to you in this case:

  • 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样式的回调转换为样式的回调,反之亦然的模块,并且与promise一样,就像 asCallback 在Bluebird中工作.如果使用回调样式对您来说更方便,那当然是可行的.

Of course I see no reason why you couldn't write a module that converts Node-style callbacks into your style callbacks or vice versa, and the same with promises, much like promisify and asCallback work in Bluebird. It certainly seems doable if working with your callback style is more convenient for you.

我刚刚在npm上发布了一个模块,您可以使用该模块来获得自己喜欢的回调样式:

I just published a module on npm that you can use to have your preferred style of callbacks:

您可以通过以下方式安装它并在您的项目中使用:

You can install it and use in your project with:

npm install errc --save

它允许您使用如下代码:

It allows you to have a code like this:

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));

有关更多示例,请参见:

For more examples see:

我编写此模块作为示例,以了解如何根据您的需要操纵函数和回调,但是我根据MIT许可证发布了该模块,并在npm上发布了它,因此您可以根据需要在实际项目中使用它.

I wrote this module as an example of how to manipulate functions and callbacks to suit your needs, but I released it under the MIT license and published on npm so you can use it in real projects if you want.

这证明了Node的灵活性,其回调模型以及编写更高阶函数来创建自己的适合您的API的可能性.我发布它是希望它可以作为理解Node回调样式的示例.

This demonstrates the flexibility of Node, its callback model and the possibility to write higher-order functions to create your own APIs that suit your needs. I publish it in hope that it may be useful as an example to understand the Node callback style.

这篇关于为什么节点更喜欢错误优先回调?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆