gpt4 book ai didi

javascript - 为什么 Javascript 规范设计者在 promise 中引入了 microtask

转载 作者:行者123 更新时间:2023-11-30 11:07:37 39 4
gpt4 key购买 nike

我知道一些关于 microtask 和 Promise 的事情,比如 Promise.prototype.then 中的 handler 会在调用栈为空时被排入 microtask 并执行,它可能被用来避免竞争条件或其他有关并发的内容。

但是如果我们不引入 microtask 会怎样呢?

最佳答案

让我们来看这个示例代码:

Promise.resolve("resolved").then(i => console.log("resolved"));
console.log("start");

这是一个立即(同步)解决的 promise 。当执行 then 方法时,它已经处于已解决状态。然而,对 then 的回调不会立即执行。相反,一个作业被放入作业队列(微任务)。所以我们得到这个输出:

start
resolved

你的问题是如果没有这样的作业调度它是否可以工作,这意味着回调将立即执行以便结果将是:

resolved
start

对于示例代码,这确实是一个可行的替代方案。但现在再举一个例子,其中 promise 不是由 JavaScript 代码解决的,而是由一个较低级别的事件解决的,该事件深深地埋在一个 API 中,该 API 用一个 promise 接口(interface)封装了它。假设它是一些读取文件内容的 API:

readFile(path).then((content) => console.log("file contents: " + content));
console.log("start of a lot of work");
for (let i = 0; i < 1e7; i++) {
// some work
}
console.Log("end of a lot of work");

因此,根据 Promise 规范,这将输出:

start of a lot of work
end of a lot of work
file contents: .....

现在假设工作循环需要 3 秒才能完成,并且文件读取 API 有一个将大部分工作委托(delegate)给操作系统函数的实现。这些操作系统功能将根据操作系统处理架构运行,通常是某种形式的事件驱动多任务处理。这里的本质是,操作系统将能够在 JS 循环进行的同时进行文件操作。

我们还假设文件读取在 1 秒内完成。一个事件从操作系统冒泡到 API 的非 JavaScript 中间件,准备好冒泡到 JavaScript“世界”。现在应该怎么办?我们可以想象有两种选择:

  1. 作业被放入作业队列,这表明 promise 已解决并且需要调用 then 回调。这就是它的实际工作方式。

  2. 正在运行的 JavaScript 循环被中断readFile 返回的 promise 得到解决,then 回调被调用片刻。回调完成后,被中断的执行上下文将恢复,并继续完成。

后一种机制可能会导致整个中断链,其中甚至 then 回调中的代码也可能被另一个 promise-resolution 事件中断,...等等。这可能导致必须像堆栈一样维护的执行上下文的构建。这会使代码执行变得不可预测、难以调试并且容易发生堆栈溢出。

在我看来,这些是此选项不可取的原因,也是我们拥有选项 1 的原因。即使第二个选项适用于纯粹使用 JavaScript 创建的 promise ——不依赖于一些较低级别的异步行为——如果这些 promise 与 API 提供的行为具有不同的行为,那将是奇怪的。当涉及到 then 回调执行和作业队列的使用时,它们都应该使用相同的行为。

关于javascript - 为什么 Javascript 规范设计者在 promise 中引入了 microtask,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55016554/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com