【问题标题】:Are all Node.js callback functions asynchronous?所有 Node.js 回调函数都是异步的吗?
【发布时间】:2014-03-20 00:08:44
【问题描述】:

我正在学习 Node.js,我在每个教程中听到的都是“Node 是异步且无阻塞的!”

我听说在常规浏览器 JavaScript 中只有某些东西,例如 AJAX 调用可以异步或非阻塞(使用回调)...... Node.js 也是如此,还是所有 Node.js 回调异步/非阻塞函数?

【问题讨论】:

  • 是的。这是 javascript 的本质,而不是 node.js 特有的。
  • @zsong 这并不完全准确。
  • 这完全不准确。阅读规范。完全没有关于同步/异步或阻塞/非阻塞或 io 的问题
  • 异步的不是回调。这是您将回调传递给异步的函数,因此需要回调。并不是每个接受回调的函数都这样做,因为它会做一些异步的事情。

标签: javascript node.js asynchronous


【解决方案1】:

所有的 Node.js 回调函数都是异步/非阻塞的吗?

没有。只有 I/O 通常是异步的,但许多其他回调是同步的。始终检查文档。

异步函数示例:

  • 异步Filesystem 访问(虽然它们有同步对应项,但没有回调)
  • 定时器 (setTimeout)
  • process.nextTick, setImmediate
  • 大多数数据库连接
  • 网络连接
  • Promises

同步回调示例:

另见Are all javascript callbacks asynchronous? If not, how do I know which are?(包括其他一些示例)。

【讨论】:

  • 这并不完全准确。没错,I/O 是多线程的,其余的不是,但许多其他回调仍然是异步的,并且在单独的调用堆栈中调用。
  • 其他回调是什么意思?
  • @vkurchatkin:他们还是callbacks,不是吗?
  • @vkurchatkin:传递给另一个函数以供另一个函数调用的函数是回调。同步或异步调用回调无关紧要。 ECMAScript 规范将传递给 .forEach() 的函数称为“回调”。
  • @Bergi 我只是在谈论布拉德评论中的“其他异步回调”,我同意你回答的那一部分。在这里停止偏离主题是 isaacs 的一篇有趣的帖子:blog.izs.me/post/59142742143/designing-apis-for-asynchrony 这里更多地谈论一致性(始终同步或始终异步),但仍然相关
【解决方案2】:

当您将回调传递给函数时,您希望该函数在其他时间调用您的回调函数。但是,它不会自动异步。

假设我有这个代码:

function callSomething(callback) {
  callback();
}

function theCallback() {
  // Do something time consuming here
}

callSomething(theCallback);

在这种情况下,我们传递了一个回调,但回调会立即在现有调用堆栈上调用。这被认为是不好的做法,并且在 Node.js 中强烈反对。如果您想立即调用回调,请使用process.nextTick()

function callSomething(callback) {
  process.nextTick(callback);
}

因此,您的问题的直接答案大多是肯定的。当您在 Node.js 中指定函数的回调时,按照惯例,它们将在稍后的时间点在另一个调用堆栈上调用。但是,如果您使用的是不知道如何遵循此约定的人提供的一些错误代码,则无法保证。

【讨论】:

  • 一般情况下是正确的。另外值得一提的是setImmediate 可以使用,我听到几个节点核心成员说使用它比使用nextTick 更好,以避免nextTick 特定问题(主要是IO 饥饿)
  • @vkurchatkin 有趣的是,我没听说过 setImmediate。我肯定会在我的一些项目中将其替换掉! stackoverflow.com/a/15349865/362536
【解决方案3】:

不,它们不会自动异步。考虑这段代码:

function foo(array, filter, callback) {
    var result = []
    for (var i = 0; i < array.length; i++) {
        if (filter(array[i])) result.push(array[i]);
    }

    callback(result);
}

现在想象一个这样的程序:

foo([ 1, 2, 3, 4 ], function() { while(true); }, console.log);
console.log('Blocking?');

如果foo 是异步的,那么Blocking? 会立即出现,但它不会!


但是,您可以确定,大多数/所有接受回调的标准库都是非阻塞异步代码。其中大部分还有一个Sync 对应项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-22
    • 2016-01-16
    • 1970-01-01
    • 2019-01-20
    • 2015-07-08
    • 2017-03-20
    • 1970-01-01
    相关资源
    最近更新 更多