繁体   English   中英

Node.js异步任务是否同步处理?

[英]Are Node.js asynchronous tasks handled synchronously?

考虑以下代码:

var some_expensive_task = function(i) {
    setTimeout(function() {
        var a = 1;

        while (a < 100000000) {
            Math.sqrt(a);

            ++a;
        }
        console.log('finished set' + i);
    }, 0);
};

for (var i = 0; i < 70; ++i) {
    console.log('start ' + i);
    some_expensive_task(i);
    console.log('end ' + i);
}

该程序的目的是使用setTimeout迭代并启动70个CPU密集型异步任务。

正如所料,该计划的产出是:

start 1
end 1
...
start 69
end 69
finished set1
...
finished set69

在整个执行过程中,只有两个过程。 我假设其中一个是空闲事件循环,另一个是100%运行的工作进程。

我是否正确理解当事件循环同步执行时,启动的异步任务(无论来源如何)都按照调用它们的顺序同步执行?

UPDATE

我仍然觉得我没有把我的问题清楚地表达出来。 使用setTimeout是我能想到的准确安排一堆异步函数运行的唯一方法。 我想真正的问题是,如果我用setTimeout启动三个异步函数,仍然是零延迟,是第二个我开始保证在第一个完成后运行,第三个保证在第二个完成后启动吗?

你在问题中使用了不正确的术语, Are Node.js asynchronous tasks handled synchronously没有多大意义。 测试用例不是你想象的那样。 首先明确一些术语:

保证同步函数按其调用顺序运行/完成。

异步函数可以在调用时进行并完成无序操作。

阻止操作是指一旦启动就必须完成的操作,以便执行进一步发展。 除非在单独的worker上运行,否则CPU密集型操作将被阻止。 循环本质上是阻塞的。 一旦它们启动,它们将在执行下一个函数之前完成所有迭代。

setTimeout在当前时间之后至少调用传递函数至少x ms。 调用它意味着一旦x ms通过它就会在事件循环中对传递的函数进行排队。 这只是延迟执行。

因此,考虑到上述事实,这就是为什么您的测试具有误导性的原因:

  • 首先,您的测试用例(您的CPU密集型函数)不是异步的,您将它包装在异步的setTimeout周围。 超时0仅表示它们将按照调用它们的顺序执行。 所有回调函数都是同步的。

  • 其次,日志中的开始和结束表示调用setTimeout的位置。 这将按预期顺序进行。 超时0时,完成也将按顺序完成。 是的,如果你保持超时等于他们,他们将按照通过的顺序执行。 然后,这是许多可能的情况之一,其中结果类似于同步(如果超时按递增顺序怎么办?)。 你问的问题可能适用于这些情况,但并非总是如此。

  • 第三,如果你想模拟异步性(足以看到控制台上的无序行为),可以放松while循环并使用随机超时( Math.random()*1000 )。 你会看到它们以任意方式完成。 这将是异步执行(setTimeout而不是回调)。

Node.js是单线程的,并且在一个进程中运行,因为JavaScript是单线程的。 因此你是对的。

是。 Javascript,包括NodeJS,是单线程的(除了少数例外)。

当您使用setTimeout(fn, 0) ,它会将当前调用堆栈清除后运行的函数排队。 在您的示例中,这意味着for循环将在“昂贵的任务”运行之前完成。

您的JS代码在Node.js中的单个线程中运行。 所有其他本机Node.js API都是用C / C ++编写的,可以是异步的,也可以在单独的线程上运行。 有关更详细的说明,请参阅此答案

我是否正确理解当事件循环同步执行时,启动的异步任务(无论来源如何)都按照调用它们的顺序同步执行?

是的,你是对的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM