简体   繁体   English

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

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

Consider the following piece of code: 考虑以下代码:

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);
}

The intent of this program was to iterate over and start 70 cpu intensive asynchronous tasks using setTimeout. 该程序的目的是使用setTimeout迭代并启动70个CPU密集型异步任务。

As expected, the output of this program is: 正如所料,该计划的产出是:

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

Throughtout the entire execution, there were only two processes. 在整个执行过程中,只有两个过程。 One of which I assume was the idle event loop and the other was the worker process running at 100%. 我假设其中一个是空闲事件循环,另一个是100%运行的工作进程。

Am I correct in understanding that while the event loop is executed synchronously, asynchronous tasks that are started, regardless of origin, are executed synchronously in the order that they were called? 我是否正确理解当事件循环同步执行时,启动的异步任务(无论来源如何)都按照调用它们的顺序同步执行?

UPDATE UPDATE

I still don't feel as if I've conveyed my question clear enough. 我仍然觉得我没有把我的问题清楚地表达出来。 Using setTimeout was the only way I could think of to accurately schedule a bunch of async functions to run. 使用setTimeout是我能想到的准确安排一堆异步函数运行的唯一方法。 I guess the real question is, if I start three async functions with setTimeout, still with a zero delay, is the second one I start guaranteed to run after the first one finishes and is the third one guaranteed to start after the second one finishes? 我想真正的问题是,如果我用setTimeout启动三个异步函数,仍然是零延迟,是第二个我开始保证在第一个完成后运行,第三个保证在第二个完成后启动吗?

You use incorrect terminology in the question, Are Node.js asynchronous tasks handled synchronously does not make much sense. 你在问题中使用了不正确的术语, Are Node.js asynchronous tasks handled synchronously没有多大意义。 And the test case is not what you think it is. 测试用例不是你想象的那样。 First making clear some terminologies: 首先明确一些术语:

Synchronous functions are guaranteed to run/complete in the order of their invocation. 保证同步函数按其调用顺序运行/完成。

Asynchronous functions can progress and complete out-of-order wrto their calling. 异步函数可以在调用时进行并完成无序操作。

Blocking operations are those operations which once started must complete for the execution to progress further. 阻止操作是指一旦启动就必须完成的操作,以便执行进一步发展。 CPU-intensive operations are blocking unless you run them on a separate worker. 除非在单独的worker上运行,否则CPU密集型操作将被阻止。 loops are blocking in nature. 循环本质上是阻塞的。 Once they start, they will complete all iterations before next function is executed. 一旦它们启动,它们将在执行下一个函数之前完成所有迭代。

setTimeout simply calls the passed function at least x ms after current time. setTimeout在当前时间之后至少调用传递函数至少x ms。 Calling it means once x ms pass it queues the passed function on the event loop. 调用它意味着一旦x ms通过它就会在事件循环中对传递的函数进行排队。 It is just delayed execution. 这只是延迟执行。

So considering above facts, here is why your test is misleading: 因此,考虑到上述事实,这就是为什么您的测试具有误导性的原因:

  • First your test case (your CPU-intensive function) is not asynchronous, you wrapped it around a setTimeout which is asynchronous. 首先,您的测试用例(您的CPU密集型函数)不是异步的,您将它包装在异步的setTimeout周围。 The timeout of 0 simply implies that they will be executed in the same order they are called. 超时0仅表示它们将按照调用它们的顺序执行。 All callback functions being synchronous. 所有回调函数都是同步的。

  • Second, start and end in the log indicates point where your setTimeout is called. 其次,日志中的开始和结束表示调用setTimeout的位置。 This would be in-order as expected. 这将按预期顺序进行。 With timeout 0, the completion will be in-order too. 超时0时,完成也将按顺序完成。 Yes if you keep timeout equal for them they all will be executed in the same order as passed. 是的,如果你保持超时等于他们,他们将按照通过的顺序执行。 Then again this is one of many possible cases where outcome is similar to synchronous (what if timeouts were in increasing order?). 然后,这是许多可能的情况之一,其中结果类似于同步(如果超时按递增顺序怎么办?)。 What you asked may be true for these cases but not always. 你问的问题可能适用于这些情况,但并非总是如此。

  • Third if you wanted to simulate asynchronicity (enough to see out-of-order behaviour on console), might as well loose the while loop and use random timeouts( Math.random()*1000 ). 第三,如果你想模拟异步性(足以看到控制台上的无序行为),可以放松while循环并使用随机超时( Math.random()*1000 )。 You will see they complete in arbitrary fashion. 你会看到它们以任意方式完成。 This would be asynchronous execution (of setTimeout not the callback). 这将是异步执行(setTimeout而不是回调)。

Node.js is single threaded and runs in one process because JavaScript is single threaded. Node.js是单线程的,并且在一个进程中运行,因为JavaScript是单线程的。 Thus you are correct. 因此你是对的。

Yes. 是。 Javascript, including NodeJS, is single threaded (with a few exceptions). Javascript,包括NodeJS,是单线程的(除了少数例外)。

When you use setTimeout(fn, 0) , it queues up the function to run after the current call stack has cleared. 当您使用setTimeout(fn, 0) ,它会将当前调用堆栈清除后运行的函数排队。 In your example, that means that the for loop will complete before the "expensive tasks" get run. 在您的示例中,这意味着for循环将在“昂贵的任务”运行之前完成。

Your JS code runs in a single thread in Node.js. 您的JS代码在Node.js中的单个线程中运行。 All other native Node.js API are written in C/C++ and are either asynchronous or run on a separate thread. 所有其他本机Node.js API都是用C / C ++编写的,可以是异步的,也可以在单独的线程上运行。 See this answer for the more detailed explanation. 有关更详细的说明,请参阅此答案

Am I correct in understanding that while the event loop is executed synchronously, asynchronous tasks that are started, regardless of origin, are executed synchronously in the order that they were called? 我是否正确理解当事件循环同步执行时,启动的异步任务(无论来源如何)都按照调用它们的顺序同步执行?

Yes, you are correct. 是的,你是对的。

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

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