I have a question about asynchrony in JS. How it actually works. I'm not sure if I got it right, I hope you can help me figure it out.
So, I have a code:
console.log('start');
setTimeout(() => console.log('one'), 0);
console.log('two');
setTimeout(() => console.log('three'), 3000);
console.log('finish');
console.log('start')
gets into the CallStack, executes and ride out of it. In the console, I get the output 'start'.setTimeout(() => console.log('one'), 0)
gets into CallStack, but since this is an asynchronous function from CallStack, it goes to the Web API and works there in the background. As soon as it completes, its callback function will ‘move’ to the Callback queue.console.log('two')
also gets into the CallStack, is executed and removed. In the output now we have (‘start’, ‘two’)setTimeout(() => console.log('three'), 3000);
console.log('finish')
and in the output we have (‘start’, ’two’,’finish’)console.log('one')
gets into the Call Stack, is executed and deleted. The output is (‘start’,’two’, ’finish’, ’one'), etc.It turns out that event loop checks if the CallStack is empty, if it is empty and the Callback queue contains a callback function, then it pushes them into the CallStack and does it until the Callback queue is empty?
console.log('start');
setTimeout(() => console.log('one'), 0);
console.log('two');
setTimeout(() => console.log('three'), 3000);
console.log('finish');
Something like this happens:
'start'
is printed to the consolesetTimeout
is called, supplying an anonymous callback function () => console.log('one')
and a minimum wait period (0
)'two'
is printed to the consolesetTimeout
is called, supplying an anonymous callback function () => console.log('three')
and a wait period of three seconds'finish'
is printed to the consolesetTimeout
as possible, a job is added to the macrotask job queue by the host environmentF1
for the running of the callback associated with it, and pushes it onto the call stack() => console.log('one')
is executed and 'one'
is printed to the consoleF1
is popped off the call stacksetTimeout
as possible, a job is added to the macrotask job queue by the host environmentF2
for the running of the callback associated with it, and pushes it onto the call stack() => console.log('three')
is executed and 'three'
is printed to the consoleF2
is popped off the call stackNote that jobs can only be drained from the job queue when the one and only userland thread of execution completes whatever it is doing. Your code kindly leaves the JS runtime mostly idle while you wait for the setTimeout
callbacks to be added to the job queue, meaning the callbacks are run in a timely fashion.
Note that the host environment (eg. a browser), and the JS runtime, exist outside of the single thread of execution your JS code "sees". This means that the runtime and the host environment are able to keep track of things like pending setTimeout
callbacks and job queues, without blocking your code.