javascript - 通过 promise 、任务和作业队列了解异步 JS

标签 javascript asynchronous promise event-loop job-queue

我正在研究 JS 中的异步行为,大部分情况下进展顺利。我了解执行代码的同步方式,JS 的单线程以及 setTimeout 中的回调如何由 Web 浏览器 API 计时,然后添加到任务队列中。

事件循环会不断检查调用栈,只有当它为空时(所有同步代码都已执行),它才会取任务队列中已经排队的函数。将它们推回调用堆栈并执行。

这非常简单,这就是以下代码的原因:

console.log('start');
setTimeout(() => console.log('timeout'), 0);
console.log('end');

将输出开始、结束、超时

现在,当我开始阅读 promises 时,我了解到它们比常规异步代码(如超时、间隔、事件监听器)具有更高的优先级,而是将被放置在作业队列/微任务队列中。事件循环将首先确定该队列的优先级并运行所有作业直到耗尽,然后再转到任务队列。

这仍然有意义,可以通过运行看到:

console.log('start');
setTimeout(() => console.log('timeout'), 0);
Promise.resolve().then(() => console.log('promise'));
console.log('end');

这会输出开始、结束、 promise 、超时。同步代码执行,then 回调从微任务队列被压入堆栈并执行,任务队列中的 setTimeout 回调任务被压入并执行。到目前为止一切都很好。

我完全可以理解上面的示例,在这个示例中,promise 会立即同步地得到解决,正如官方文档所述。如果我们使用 new 关键字创建一个 promise 并提供一个执行函数,也会发生同样的情况。该执行器函数将同步执行并解析该函数​​。所以当遇到 then 时,它可以在已解决的 promise 上异步运行。

console.log('start');

const p1 = new Promise(resolve => {
    console.log('promise 1 log');
    resolve('promise 1');
});

p1.then(msg => console.log(msg));

console.log('end');

上面的代码片段将输出 start, promise 1 log, end, promise 1 证明执行器是同步运行的。

这就是我对 promises 感到困惑的地方,假设我们有以下代码:

console.log('start');

const p1 = new Promise(resolve => {
    console.log('promise 1 log');
    setTimeout(() => {
        resolve('promise 1');
    }, 0);
});

p1.then(msg => console.log(msg));

console.log('end');

这将导致 start, promise 1 log, end, promise 1。如果执行器函数立即执行,则意味着其中的 setTimeout 将被放入任务队列以供稍后执行。据我了解,这意味着该 promise 目前仍在等待中。我们到达 then 方法和其中的回调。这将被放入作业队列。其余的同步代码被执行,我们现在有了空的调用堆栈。

据我了解,promise 回调现在具有优先权,但它如何执行尚未解决的 promised? promise 应该只在其中的 setTimeout 执行后解析,它仍然位于任务队列中。我听说,没有任何额外的说明,只有在 promise 得到解决时才会运行,从我的输出中我可以看到这是真的,但我不明白在这种情况下它是如何工作的。我唯一能想到的是异常或类似的东西,并且任务队列任务在微任务之前获得优先级。

这最终很长,所以我感谢任何人花时间阅读并回答这个问题。我很想更好地理解任务队列、作业队列和事件循环,所以请不要犹豫,发布详细的答案!提前谢谢你。

最佳答案

We get to the then method and the callback within it. This will be put in the job queue.

不,调用 then 不会在 promise 仍未决时立即将任何内容放入作业队列。回调将安装在 promise 上,以便稍后在 promise 完成时执行,就像事件处理程序一样。只有当您调用 resolve() 时,它才会真正将其放入作业队列。

这就像 setTimeout 一样工作,您在其中写道“[the] 回调 […] 将由 Web 浏览器 API 计时,稍后添加到任务队列中” - 它不会立即将等待的任务加入队列,而是等待并然后将任务加入队列以执行回调。

关于javascript - 通过 promise 、任务和作业队列了解异步 JS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63257952/

相关文章:

c# - 在返回具体类之前调用​​异步方法的工厂

c# - Backgroundworker C#中 "WorkerSupportCancellation"的意义是什么

node.js - Mongoose save() 不返回 promise

javascript - 连接 promise ,或者一个 promise 触发另一个 promise

javascript - 在 Promise 链中包含 if-else 条件

javascript - material-ui 组件 |日期选择器 |没有数据传递给 onChange

javascript - 未找到 React Router v5 嵌套路由

swift - 从服务器异步下载信息

javascript - 如果值为空,则 sap.m.Text 的日期格式化程序不可见

javascript - 两个表格垂直对齐,如何同步宽度/间距?