So this program is executing from top to bottom. And when we call the function doLater, the function gets pushed onto the call stack. So now there's going to be one entry here for doLater. And then inside of the doLater function, if it calls any additional functions, those will be pushed onto the call stack and the call stack will grow up like this. And we can see that in the Chrome debugger when we're debugging our code.
So how can we get a function on to the task queue? Well, one of the first things we can use is a timer. So a timer allows us to execute some function at a later time. And it does that by using the task queue.
The first timer function we can use is SetTimeout. So calling the SetTimeout function will put another function onto the call stack. I'll just abbreviated it here. Oh, maybe I can fit it in. SetTimeout.
And what this will do is call into a native function in Node.js or in the browser that says take this function that we passed in as a parameter. And in 3,000 milliseconds or three seconds, put this function at the end of the line on the task queue. And then the function will return immediately, and that puts us back down here.
And then finally, everything will have returned and both of these functions will be popped off the call stack and it will be empty. Now, Node.js down here running below-- so this is machinery that's not in our program but that's running nonetheless-- in 3,000 milliseconds will take that function and put it at the end of the task queue line. So there's nothing in the task queue currently, so that will just go right in here at the beginning of the line.
Now we can use the same machinery to do I/O whether it be reading a file or making a network request to MongoDB. Let's pretend, for example, that we're reading in a file so we use the Node.js FS module and call the readFile method, passing the path to the file and then a function callback that takes an error and a result as parameters.
So as soon as we call this function that puts a function onto the call stack. And what this does is it calls into the Node.js runtime. And what the Node.js runtime does is it starts a job to read in this file. So we're going to do some I/O here, and the I/O is going to be to read in a file.
And then it'll store away this callback function. And when the I/O work has done reading in the file, it can take the function and put it at the beginning of the task queue, just like we did with SetTimeout. Now, the difference between SetTimeout and I/O is that with I/O, we're actually doing some real work. And that's happening concurrently with the rest of our program.
So in other words, it's happening at the same time and the task queue can continue to be processed and our code can continue to execute while the operating system is reading in this file. So all of this is being handled concurrently by Node.js.
Now, once we have a file, the Node.js runtime will take this function and put it at the beginning of the queue. So we'll just put that here as an example. And when it makes its way to the front of the line, the event loop will pick it up and our callback inside of here will start to execute.
So this is also asynchronous in that this function here gets run at a later time. But because we're doing I/O work, reading from a file or making a network request, Node.js also makes that concurrent and so it's able to happen at the same time as the rest of our code. So other types of I/O down here that we could do would be making a request to Mongo, for example, or any kind of network request, TCP.
Or we could be writing a file and so on. And all of these can happen in parallel, and Node manages all of that for us automatically. So this is a simple method for concurrency because all we have to do is to call these functions, which are asynchronous, like readFile, and pass them in these callbacks. And the callbacks will just get executed at a later time when we have results.
And we don't have to worry about things like threading or multiple processes. So the whole idea here is to provide a simple way to get some concurrency between using the CPU and doing I/O. Being able to visualize this diagram will be useful in all sorts of tasks, but as we start talking about fibers I'd recommend that you keep this diagram in your head, and maybe even draw it out to help you see what's going on in programs that use fibers.