2
"use strict"

const
    fs = require('fs'),
    stream = fs.createReadStream("file.txt"),
    timeout = 0;

stream.on('data', function() {
    console.log("File Read");
});

setTimeout(function(){
    console.log("setTimeout : " + timeout);
}, timeout);

I'm learning node.js / javascript and I was wondering why is this program returning

setTimeout : 0
File Read

and not the other way around.

Correct me if I'm wrong but in javascript the callback queue is fifo, stacking the stream first and out first?

I think that because of the non-blocking nature of nodejs, both callback are run in "parallel" and setTimeout finishes first and return (for example a timeout of 1000ms would switch the results.)

3 Answers 3

6

Correct me if I'm wrong but in javascript the callback queue is fifo, stacking the stream first and out first?

Not quite. Async callbacks are processed FIFO in the order they complete their operations, not in the order their operations were started. So, the amount of time the operation takes to complete is very important in determining when the callback gets scheduled. Short operations may complete before long operations, even if they were started later.

It takes time to open a file and start reading it and the setTimeout() takes no time so it occurs first. When you have independent asynchronous operations, you can almost never "know" what order they will occur in because it depends upon the internal timing of the various functions.

The readStream operation gets started before the timer gets started, but the timer finishes before the readStream operation gets its first data just due to the amount of work required internally for the two async operations.

I think that because of the non-blocking nature of nodejs, both callback are run in "parallel" and setTimeout finishes first and return (for example a timeout of 1000ms would switch the results.)

Yes, this is correct.


Think of it like this. You have two powerful megaphones and a really good microphone. You set up two targets to point the megaphone at and listen for the returned echo. One target ie very close and one target is very far away. You first blast the megaphone at the very far away target, then immediately blast the megaphone at the near target. In no surprise, you get the echo from the near target first even though you sent its blast after the first one, simply because the echo from the far away target takes a lot longer to traverse all its extra distance and get back to you. The same is true of your readStream. Even though you started it first, it takes a lot longer than a setTimeout(fn, 0) so the setTimeout() finishes first and thus calls its callback first.


If the timing is important to you, then you SHOULD use tools like promises to specifically sequence your async operations or to wait until all necessary results are ready. A good design should not "assume" that one async operation will complete before another unless your code specifically guarantees that by sequencing the operations.

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

Comments

0

It is surprising that I did a video tutorial explaining this concept 2 days ago and you have asked this. Do watch this 9 min video to get a good understanding of this. Here is the explaination. There is a concept called Eventloop in Nodejs and in JS in general. What an Eventloop does is that it keeps a watch on the code that is running and on the stack. As you said what ever is pushed onto the stack from code block is a FIFO. However if there are any async or callback methods or actions that have to be performed then Eventloop jumps into action to take care of these. What eventloop essentially does 8s that it has a queue of its own where it maintains these callback methods. When the stack is free, this piece of code from queue is put onto the stack and is executed.

Comments

0

This is purely because of node js's IO non blocking feature. Your file read operation is an IO thing hence it will be pushed to event queue and the setTimeOut function will be executed immediately. Once the file read is done, using its callback it will join the main control flow. Hence setTimeOut will be executed first and then the File read. Simple.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.