4

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?

3
  • 1
    I think you need to make a distinction between the asynchronous task (wait for 0 ms) and the callback (cpu intensive synchronous loop) Commented Aug 20, 2014 at 10:10
  • @Bergi, I suppose the task in this case was just meant to provide a sort of in-function delay to illustrate the order in which things are executed. Commented Aug 20, 2014 at 21:16
  • You probably want to take a look at the child_process module at nodejs.org/api/child_process.html if you want multithreading. Commented Aug 22, 2014 at 2:24

4 Answers 4

3

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 w.r.to 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).

Sign up to request clarification or add additional context in comments.

24 Comments

Asynchronous functions can progress and complete out-of-order w.r.to their calling. I don't understand this sentence. Functions are always synchronous from the entry point to the exit point. They may schedule tasks to be called later but it doesn't mean that they do anything out-of-order. At least this is not a formal definition. There is no such thing as asynchronous functions to be formal. And thus there is no such thing as synchronous functions. There are only functions.
To elaborate a bit more: is this function var L = []; function T(x) { L.push(x); } synchronous or asynchronous?
@freakish: There are no "asynchronous functions" in javascript, that's right. All functions run synchronously until they return to their caller. However, the environment gives us some functions that take a callback function, start an asynchronous task and schedule the callback for when that is finished, and return immediately. setTimeout is such an environment function: it synchronously, immediately returns a timer id, and internally schedules the callback to be invoked in any order in the future. Of course, the execution of that javascript function runs synchronously then.
@user568109: setTimeout is always asynchronous, even if you pass a timeout of 0 ms. It never runs the callback before it returns.
Maybe the correct question is: do asynchronous tasks block other asynchronous tasks?
|
2

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

Comments

0

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.

Comments

0

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.