作业队列如何与承诺一起工作? [英] How Job queue works with promise?
问题描述
我正在学习 JS 中的 Promise,并对 Promise 在幕后如何与作业队列一起工作感到好奇.为了解释我的困惑,我想向您展示这段代码:
new Promise(function(resolve, reject) {setTimeout(() => resolve(1), 1000);}).then(函数(结果){警报(结果);//1return new Promise((resolve, reject) => {//(*)setTimeout(() => resolve(result * 2), 1000);});})
看上面的代码,是不是 then() 的回调是提前放入Job队列等待promise解析的?还是只有在 promise 得到解决后才将 then() 的回调推入作业队列?
当需要调用 promise 回调时,该作业根本不会进入标准作业队列 (ScriptJobs);它进入 PromiseJobs 队列.PromiseJobs 队列一直被处理,直到 ScriptJobs 队列中的每个作业结束时它都为空.(规范中的更多内容:作业和作业队列.)
我不确定您期望从代码中得到什么输出,正如您没有说的那样,但让我们举一个更简单的例子:
console.log("top");新承诺(解决 => {setTimeout(() => {console.log("定时器回调");}, 0);解决();}).then(() => {console.log("然后回调 1");}).then(() => {console.log("然后回调 2");});console.log("bottom");
可靠的输出是:
<预>最佳底部然后回调1然后回调2定时器回调因为:
- 运行该脚本的 ScriptJobs 作业
console.log("top")
运行- promise executor 函数代码运行,其中
- 为立即"安排计时器作业这将立即或几乎立即进入 ScriptJobs 队列
- 通过不带参数调用
resolve
来实现承诺(这意味着在对它调用then
之前解决了承诺)(这实际上就像用undefined
,不是 thenable 触发承诺的履行).
- 第一个
then
连接第一个履行处理程序,排队 PromiseJobs 作业,因为承诺已经履行 - 第二个
then
连接第二个执行处理程序(不排队作业,等待第一个then
的承诺) console.log(bottom")
运行- 当前的 ScriptJob 作业结束
- 引擎处理正在等待的 PromiseJobs 作业(第一个履行处理程序)
- 输出
"then callback 1"
并实现第一个then
的承诺(通过返回) - 这将 PromiseJobs 队列上的另一个作业排队,以回调到第二个执行处理程序
- 由于 PromiseJobs 队列不为空,下一个 PromiseJob 被拾取并运行
- 第二个履行处理程序输出
"then callback 2"
- PromsieJobs 为空,因此引擎会选择下一个 ScriptJob
- 那个 ScriptJob 处理定时器回调并输出
定时器回调"
在 HTML 规范中,它们使用的术语略有不同:任务";(或宏任务")用于 ScriptJobs 作业和微任务"PromiseJobs 工作(和其他类似工作).
关键点是:在 ScriptJob 期间排队的所有 PromiseJob 都会在该 ScriptJob 完成时处理,其中包括任何 PromiseJobs they 队列;只有当 PromiseJobs 为空时,下一次 ScriptJob 才会运行.
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?
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:
- The ScriptJobs job to run that script runs
console.log("top")
runs- The promise executor function code runs, which
- Schedules a timer job for "right now," which will go on the ScriptJobs queue either immediately or very nearly immediately
- Fulfills the promise (which means the promise is resolved before
then
is called on it) by callingresolve
with no argument (which is effectively like calling it withundefined
, which not being thenable triggers fulfillment of the promise).
- The first
then
hooks up the first fulfillment handler, queuing a PromiseJobs job because the promise is already fulfilled - The second
then
hooks up the second fulfillment handler (doesn't queue a job, waits for the promise from the firstthen
) console.log("bottom")
runs- The current ScriptJob job ends
- The engine processes the PromiseJobs job that's waiting (the first fulfillment handler)
- That outputs
"then callback 1"
and fulfills the firstthen
's promise (by returning) - That queues another job on the PromiseJobs queue for the callback to the second fulfillment handler
- Since the PromiseJobs queue isn't empty, the next PromiseJob is picked up and run
- The second fulfillment handler outputs
"then callback 2"
- PromsieJobs is empty, so the engine picks up the next ScriptJob
- That ScriptJob processes the timer callback and outputs
"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.
这篇关于作业队列如何与承诺一起工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!