作业队列如何与承诺一起工作? [英] How Job queue works with promise?

查看:49
本文介绍了作业队列如何与承诺一起工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习 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定时器回调

因为:

  1. 运行该脚本的 ScriptJobs 作业
  2. console.log("top") 运行
  3. promise executor 函数代码运行,其中
    • 为立即"安排计时器作业这将立即或几乎立即进入 ScriptJobs 队列
    • 通过不带参数调用 resolve 来实现承诺(这意味着在对它调用 then 之前解决了承诺)(这实际上就像用 undefined,不是 thenable 触发承诺的履行).
  4. 第一个 then 连接第一个履行处理程序,排队 PromiseJobs 作业,因为承诺已经履行
  5. 第二个 then 连接第二个执行处理程序(不排队作业,等待第一个 then 的承诺)
  6. console.log(bottom") 运行
  7. 当前的 ScriptJob 作业结束
  8. 引擎处理正在等待的 PromiseJobs 作业(第一个履行处理程序)
  9. 输出 "then callback 1" 并实现第一个 then 的承诺(通过返回)
  10. 这将 PromiseJobs 队列上的另一个作业排队,以回调到第二个执行处理程序
  11. 由于 PromiseJobs 队列不为空,下一个 PromiseJob 被拾取并运行
  12. 第二个履行处理程序输出"then callback 2"
  13. PromsieJobs 为空,因此引擎会选择下一个 ScriptJob
  14. 那个 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:

  1. The ScriptJobs job to run that script runs
  2. console.log("top") runs
  3. 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 calling resolve with no argument (which is effectively like calling it with undefined, which not being thenable triggers fulfillment of the promise).
  4. The first then hooks up the first fulfillment handler, queuing a PromiseJobs job because the promise is already fulfilled
  5. The second then hooks up the second fulfillment handler (doesn't queue a job, waits for the promise from the first then)
  6. console.log("bottom") runs
  7. The current ScriptJob job ends
  8. The engine processes the PromiseJobs job that's waiting (the first fulfillment handler)
  9. That outputs "then callback 1" and fulfills the first then's promise (by returning)
  10. That queues another job on the PromiseJobs queue for the callback to the second fulfillment handler
  11. Since the PromiseJobs queue isn't empty, the next PromiseJob is picked up and run
  12. The second fulfillment handler outputs "then callback 2"
  13. PromsieJobs is empty, so the engine picks up the next ScriptJob
  14. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆