【问题标题】:why do i need 2 parameters for callback?为什么我需要 2 个回调参数?
【发布时间】:2016-02-27 05:53:44
【问题描述】:

我在节点脚本中有一个简单的异步阅读器阅读 firefox-json-bookmarks。 当我删除回调函数中的第一个参数 (err) 时,出现错误。 是什么原因?为什么 err 与 e 不同?

app.js

var fs = require('fs'), obj;
fs.readFile(__dirname + '/bookmarks.json', 'utf8', handleFile);

function handleFile( err, data ) { // why is the first parameter needed?

    try {
        obj = JSON.parse( JSON.stringify(data) );
        console.log(obj);

    } catch (e) {
        console.log(e);
        //console.log(err);
    }
}

【问题讨论】:

标签: json file parsing fs


【解决方案1】:

每次调用函数时,该函数都会被压入称为调用堆栈的函数堆栈中。当该函数返回一个值时,它会从堆栈中弹出。调用堆栈描述了您在程序中的位置以及您是如何到达那里的。

同步码

想象一下整个程序过程中的调用堆栈。

function a() { return b() }
function b() { return c() }
function c() { throw new Error() }
a();

首先,a 被调用,所以我们将它添加到堆栈中。

[ a ]

然后a 调用b,所以我们也将它添加到堆栈中。

[ a, b ]

然后b 调用c

[ a, b, c ]

然后c 抛出一个错误。此时,调试器可以告诉您c 是引发错误的函数,并且您通过ab 最终到达c。这适用于常规同步代码,例如 JSON.parse

异步代码

函数返回后,异步代码继续运行。例如:

function a() {
  setTimeout(function() { console.log(2); }, 10000);
  return 1;
}

如果你调用a,那么它将被压入调用堆栈,然后返回1并从调用堆栈中弹出。大约 10 秒后,2 将打印到控制台中。

如果超时这样做会发生什么?

function a() {
  setTimeout(function() { throw new Error(); }, 10000);
  return 1;
}

错误将被抛出,但调用堆栈将为空。可以想象,这对开发人员来说并不是很有用。

如果我们想异步返回一个值,这也是一个问题。当异步事件发生时(超时、读/写、网络等),函数已经返回。

相反,我们可以使用一种称为Continuation-Passing Style 的形式,通常称为回调。除了调用我们的异步函数,我们还向它传递函数(一个延续),我们要求它在完成后运行。请记住,这可以在函数返回值之后!

在 Node.js 中,这些回调有两个目的:

错误

如果在执行异步工作时发生错误,标准做法是将错误作为第一个参数调用回调。您会经常看到以下代码。

foo.doAsyncBar(function(err, baz) {
  if(err) throw err;
  // do something with baz
});

通过将错误传递给回调而不是抛出它,我们能够自行决定如何最好地处理它。我们可以直接扔,如上图,也可以用更优雅的方式处理。

返回

希望函数不会出错,在这种情况下,一般做法是将null 作为第一个参数传递给回调。这让编写处理代码的开发人员知道函数没有出错并且返回值在下一个参数之一中。

有关 Node.js 错误处理的更深入的文章,请参阅 Joyent 的 Production Practices document for Errors

【讨论】:

  • 谢谢。但是可以吗,当我不抛出错误并且只做: if (err) return console.error(err); ?
  • 视情况而定。这样你会看到错误,但程序可能会停止工作而不会崩溃——你可能会开始丢失数据。如果您抛出错误,那么您可以保证程序将停止。如果这是一个非严重错误,那么您可以使用 console.warn 并明确说明它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-18
  • 1970-01-01
  • 1970-01-01
  • 2019-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多