Consider the following code:
function foo() {
console.log('foo');
new Promise(
function(resolve, reject) {
setTimeout(function() {
resolve('RESOLVING');
}, 5000);
}
)
.then(
function(value) {
console.log(value);
}
);
}
foo();
I am trying to understand what happens here correctly:
new Promise
the "executer function" is run directly and when setTimeout
is called, an operation to add a new entry to the "event queue" is scheduled (for 5 seconds later)then
an operation to add to a "job queue" a call to the passed function (which logs to the console) is organised to happen after the Promise
is resolvedsetTimeout
callback is executed (on some tick of the event loop), the Promise
is resolved and based on point 2, the function argument to the then
call is added to a "job queue" and subsequently executed.Notice I say [a "job queue"] because there is something I am not sure about; which "job queue is it?". The way I understand it, a "job queue" is linked to an entry on the "event queue". So would that be the setTimeout
entry in above example?
Assuming no other events are added to the "event queue" before (and after) setTimeout
's callback is added, wouldn't the entry for the main code (the call to foo) have been (usually) gone (run to completion) by that time and thus there would be no other entry than setTimeout
's for the then
's "job queue" entry to be linked to?
JavaScript has a runtime model based on an event loop, which is responsible for executing the code, collecting and processing events, and executing queued sub-tasks. This model is quite different from models in other languages like C and Java.
The Event Loop has one simple job — to monitor the Call Stack and the Callback Queue. If the Call Stack is empty, the Event Loop will take the first event from the queue and will push it to the Call Stack, which effectively runs it. Such an iteration is called a tick in the Event Loop.
The event loop is a constantly running process that monitors both the callback queue and the call stack. If the call stack is not empty, the event loop waits until it is empty and places the next function from the callback queue to the call stack.
- on executing
new Promise
the "executer function" is run directly and whensetTimeout
is called, an operation to add a new entry to the "event queue" is scheduled (for 5 seconds later)
Yes. More specifically, calling setTimeout
schedules a timer with the browser's timer mechanism; roughly five seconds later, the timer mechanism adds a job to the main job queue that will call your callback.
- because of the call to
then
an operation to add to a "job queue" a call to the passed function (which logs to the console) is organised to happen after thePromise
is resolved
Right. then
(with a single argument) adds a fulfillment handler to the promise (and creates another promise that it returns). When the promise resolves, a job to call the handler is added to the job queue (but it's a different job queue).
- when the
setTimeout
callback is executed (on some tick of the event loop), thePromise
is resolved and based on point 2, the function argument to thethen
call is added to a "job queue" and subsequently executed.
Yes, but it's not the same job queue. :-)
The main job queue is where things like event handlers and timer callbacks and such go. The primary event loop picks up a job from the queue, runs it to completion, and then picks up the next job, etc., idling if there are no jobs to run.
Once a job has been run to completion, another loop gets run, which is responsible for running any pending promise jobs that were scheduled during that main job.
In the JavaScript spec, the main job queue is called ScriptJobs, and the promise callback job queue is PromiseJobs. At the end of a ScriptJob, all PromiseJobs that have been queued are executed, before the next ScriptJob. (In the HTML spec, their names are "task" [or "macrotask"] and "microtask".)
And yes, this does mean that if Job A and Job B are both queued, and then Job A gets picked up and schedules a promise callback, that promise callback is run before Job B is run, even though Job B was queued (in the main queue) first.
Notice I say [a "job queue"] because there is something I am not sure about; which "job queue is it?"
Hopefully I covered that above. Basically:
requestAnimationFrame
callbacks are queued to the ScriptJobs queue (the main one); they're "macrotasks" (or simply "tasks").The way I understand it, a "job queue" is linked to an entry on the "event queue".
Those are just different names for the same thing. The JavaScript spec uses the terms "job" and "job queue." The HTML spec uses "tasks" and "task queue" and "event loop". The event loop is what picks up jobs from the ScriptJobs queue.
So would that be the
setTimeout
entry in above example?
When the timer fires, the job is scheduled in the ScriptJobs queue.
Assuming no other events are added to the "event queue" before (and after)
setTimeout
's callback is added, wouldn't the entry for the main code (the call to foo) have been (usually) gone (run to completion) by that time and thus there would be no other entry thansetTimeout
's for thethen
's "job queue" entry to be linked to?
Basically yes. Let's run it down:
foo
and calls it.foo
, you do the console.log
and then create a promise.then
adds a fulfillment handler to the promise.console.log
More to explore:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With