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

IT技术 javascript node.js asynchronous
2021-02-01 03:14:11

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

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

3个回答

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

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

异步函数示例:

  • 异步文件系统访问(尽管它们具有没有回调的同步副本)
  • 计时器 ( setTimeout)
  • process.nextTick, setImmediate
  • 大多数数据库连接
  • 网络连接
  • Promise

同步回调示例:

另请参阅所有 javascript 回调都是异步的吗?如果不是,我怎么知道哪些是?(包括一些其他示例)。

@vkurchatkin:传递给另一个函数以供另一个函数调用的函数是回调。回调是同步调用还是异步调用无关紧要。ECMAScript 规范将传递给的函数.forEach()称为“回调”。
2021-03-21 03:14:11
你是指什么其他回调?
2021-04-01 03:14:11
这并不完全准确。您是对的,I/O 是多线程的,其余的不是,但许多其他回调仍然是异步的,并在单独的调用堆栈中调用。
2021-04-04 03:14:11
@vkurchatkin:它们仍然是回调,不是吗?
2021-04-07 03:14:11
@Bergi 我只是在谈论 Brad 评论中的“其他异步回调”,我同意你回答的那部分。在这里停止离题是 isaacs 的一篇有趣的帖子:blog.izs.me/post/59142742143/designing-apis-for-asynchony这里更多地讨论了一致性(始终同步或始终异步),但仍然相关
2021-04-13 03:14:11

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

假设我有这个代码:

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 饥饿)
2021-03-18 03:14:11
@vkurchatkin 有趣,我没有听说过 setImmediate。我肯定会在我的一些项目中换掉它! stackoverflow.com/a/15349865/362536
2021-04-04 03:14:11

不,它们不是自动异步的。考虑这个代码:

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对应物。