我正在学习 Node.js,并且掌握了有关异步非阻塞 I/O 的大部分基础知识。我的问题是,当函数本身不是异步时,创建带有回调的函数有什么意义。即使您正在创建的函数调用了异步函数,我也找不到您使用回调的原因。我在我正在查看的 Node.js 代码中经常看到这种情况。
例如,发送 HTTP 请求并返回请求的解析输出的函数:
function withCallback(url, callback) {
request(url, function(err, response, html) {
if (err)
callback(err, null);
callback(null, JSON.parse(html));
});
}
function withoutCallback(url) {
request(url, function(err, response, html) {
if (err)
throw err;
return JSON.parse(html);
});
}
第一个带有回调的函数通过回调返回结果,而第二个函数只是正常返回结果。
最佳答案
本来想写评论,但是有点太长了。
您问了几个问题。为了解决评论者提出的非常正确的观点,第二个示例将不起作用,并且正如 @Hawkings 更清楚地指出的那样,无法(通过您的代码)捕获结果。它不起作用,因为第二个示例中的 return
正在调用您正在创建的匿名函数(实际回调被传递给 request
),并在内部深处返回其结果请求
函数。此外,在您的示例中,控制权早在调用 return JSON.parse()
行之前就已经返回到 withoutCallback
的调用者,并且如所写的, foo = withoutCallback(...)
将导致 foo
未定义。
如果您查看使用回调的库的代码,您将看到它们是如何被调用的,并且可能更容易理解为什么这不起作用。 (尽管我建议查看一个比 request 更简单的库 - 如果您对 Node 相当陌生,我认为您会发现 request 库有点令人困惑)。
但是,就您所说的情况而言,您的问题是(您的示例中未说明):“我的问题是,当函数本身不是异步的时,创建带有回调的函数有什么意义[?]”
在这种特定情况下没有多大意义,除非a)您想在未来证明它,以防它由于添加的功能而变得异步,或者b)您希望有一个通用接口(interface),其中其他实现将是异步的。使用浏览器示例只是因为它很容易想到,如果您正在实现一个通用的基本数据存储解决方案,其中一个实现将使用 LocalStorage (同步),但其他实现可能使用 IndexedDB 或远程调用(均为异步) -您仍然希望使用回调编写 LocalStorage 实现,以便可以轻松地在实现之间切换。
如果您不喜欢回调风格,请考虑学习使用和使用利用其他技术或语言功能来处理异步性的库,包括 Promises、Generators 或在适用情况下的 EventEmitters。我个人是 Promise 的忠实粉丝。话虽如此,在您了解回调的方式和原因之前,我不会建议其中任何一个。
关于javascript - Node.js 中不必要的回调使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33182119/