Reputation: 229
I was learning promises in JS and got curious on how promises work with Job queues behind the scenes. To explain my confusion I want to show you this code:
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000);
}).then(function(result) {
alert(result); // 1
return new Promise((resolve, reject) => { // (*)
setTimeout(() => resolve(result * 2), 1000);
});
})
If you look at the above code, is it true that the callback of then() is put into Job queue beforehand and waits for promise to resolve? Or Is it true that callback of then() is pushed into job queue only after promise gets resolved?
Upvotes: 4
Views: 4393
Reputation: 1074058
When it's time to call a promise callback, the job doesn't go on the standard job queue (ScriptJobs) at all; it goes on the PromiseJobs queue. The PromiseJobs queue is processed until it's empty when each job from the ScriptJobs queue ends. (More in the spec: Jobs and Job Queues.)
I'm not sure what output you were expecting from your code as you didn't say, but let's take a simpler example:
console.log("top");
new Promise(resolve => {
setTimeout(() => {
console.log("timer callback");
}, 0);
resolve();
})
.then(() => {
console.log("then callback 1");
})
.then(() => {
console.log("then callback 2");
});
console.log("bottom");
The output of that, reliably, is:
top bottom then callback 1 then callback 2 timer callback
because:
console.log("top")
runsthen
is called on it) by calling resolve
with no argument (which is effectively like calling it with undefined
, which not being thenable triggers fulfillment of the promise).then
hooks up the first fulfillment handler, queuing a PromiseJobs job because the promise is already fulfilledthen
hooks up the second fulfillment handler (doesn't queue a job, waits for the promise from the first then
)console.log("bottom")
runs"then callback 1"
and fulfills the first then
's promise (by returning)"then callback 2"
"timer callback"
In the HTML spec they use slightly different terminology: "task" (or "macrotask") for ScriptJobs jobs and "microtask" for PromiseJobs jobs (and other similar jobs).
The key point is: All PromiseJobs queued during a ScriptJob are processed when that ScriptJob completes, and that includes any PromiseJobs they queue; only once PromiseJobs is empty is the next ScriptJob run.
Upvotes: 6
Reputation: 414
I would say callback of then()
is pushed into job queue only after promise gets resolved.
If you changed the first timeout to 3000, you run the code and it waits until 3's to alert 1. This is because you have to wait the promise to be resolved in 3 seconds.
You get get the answer from here: https://stackoverflow.com/a/30910084/12733140
promiseA.then()'s callback is a task
- promiseA is resolved/rejected: the task will be pushed into microtask queue in current round of event loop.
- promiseA is pending: the task will be pushed into microtask queue in the future round of event loop(may be next round)
So here microtask is the same as "job" as you mentioned above, only the promise is resolved or rejected, the callback will be pushed to job/microtask queue.
Upvotes: 1