简体   繁体   中英

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.

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%.

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

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. 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?

You use incorrect terminology in the question, Are Node.js asynchronous tasks handled synchronously does not make much sense. 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. 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. Calling it means once x ms pass it queues the passed function on the event loop. 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. The timeout of 0 simply implies that they will be executed in the same order they are called. All callback functions being synchronous.

  • Second, start and end in the log indicates point where your setTimeout is called. This would be in-order as expected. With timeout 0, the completion will be in-order too. 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 ). You will see they complete in arbitrary fashion. This would be asynchronous execution (of setTimeout not the callback).

Node.js is single threaded and runs in one process because JavaScript is single threaded. Thus you are correct.

Yes. Javascript, including NodeJS, is single threaded (with a few exceptions).

When you use setTimeout(fn, 0) , it queues up the function to run after the current call stack has cleared. In your example, that means that the for loop will complete before the "expensive tasks" get run.

Your JS code runs in a single thread in Node.js. All other native Node.js API are written in C/C++ and are either asynchronous or run on a separate thread. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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