最近我遇到了一个问题:

console.log("start");

const promise1 = Promise.resolve().then(() => {
  console.log("promise1");
  const timer2 = setTimeout(() => {
    console.log("timer2");
  }, 0);
});

const timer1 = setTimeout(() => {
  console.log("timer1");
  const promise2 = Promise.resolve().then(() => {
    console.log("promise2");
  });
}, 0);

console.log("end");

我最初的答案是start, end, promise1, timer2, promise2, timer1(错误的一个).

我知道同步代码首先执行,然后是微任务,然后是macrotask.我也知道微任务可能出现在两个macrotask之间.我有点困惑,也不清楚为什么当我们在callstack中执行promise1时,macrotask没有排队timer2.我也理解JS引擎读取并排队timer1,而我们正在处理promise1,但不能完全理解它的原因.

对我来说,全局声明的值似乎是先读取的.

下面是解决问题顺序的原则:

  1. 首先,所有的微观任务都要完成.(我假设这意味着所有全局微任务优先.
  2. 执行一个宏任务.
  3. 所有(重新添加的)微任务都是重新任务.
  4. 执行以下宏问题.
  5. 循环重复/循环结束.

根据这一原则,似乎首先考虑全球价值观.我理解答案背后的逻辑,但找不到任何关于"全局值被视为第一个语句"是否正确的答案.我不知道为什么timer2在处理promise1时没有排队.我有点相信它是排队的,但timer1的处理速度比timer2快,因为它是全局声明的.timer1是否先读取并在timer2之前排队,因为它在全局作用域中?这是什么原因?我有点理解,但不完全肯定.

推荐答案

但对于"全局值被视为第一陈述"是否正确,却找不到任何答案.我不知道为什么当我们处理promise1时timer2没有排队.我有点相信它是排队的,但timer1的处理速度比timer2快,因为它是全局声明的.timer1是否先读取并排在timer2之前,因为它在全局作用域中?

这不是真正的范围,而是执行顺序.正如您提到的,同步代码首先发生,同步代码的一部分是设置timer1.设置timer2是同步代码的一部分;它在稍后发生.

这是发生的顺序.首先,同步的东西:

  1. 日志(log)"开始"
  2. 创建一个已解决的promise,并调用它.then以生成promise1.
  3. 启动计时器1.也就是说,请求浏览器在将来某个时候应该排队一个macrotask.
  4. 日志(log)"结束"

现在完成了,代码执行返回.有一个微任务等待运行(与promise1相关的.then个微任务),所以它接下来运行.

  1. 日志(log)"promise1"
  2. 启动计时器2.也就是说,请求浏览器在将来某个时候应该排队一个macrotask.

现在一切都结束了,暂时也没什么可做的了.在最小定时器延迟过go 后,定时器开始关闭.我不确定这两个任务是在完全相同的时间插入到队列中,还是在时间上稍微分开.但是任务的顺序总是相同的(它们创建的顺序相同,假设它们具有相同的延迟),所以它不会影响记录的输出.让我们假设两个macrotask同时排队.因此,我们在队列中有2个宏任务,它处理第一个,用于timer1:

  1. 删除"timer1"
  2. 创建一个已解析的promise,并对其调用.then以创建promise2

当返回时,有一个微任务(与promise2相关的.then)和一个宏任务(定时器2)等待运行.微任务首先运行:

  1. Select "promise2"

当这个返回时,有一个macrotask等待运行,所以接下来运行:

  1. "timer2"

timer1是否先读取并排在timer2之前,因为它在全局作用域中? 它与作用域无关,只是创建timer1是同步代码的一部分,创建timer2只在稍后发生.

Javascript相关问答推荐

如何访问Json返回的ASP.NET Core 6中的导航图像属性

如何判断属于多个元素的属性是否具有多个值之一

我可以使用CSS有效地实现最大宽度=100%和最大高度=100%,而无需父母有明确的/固定的宽度和高度,替代方法吗?

成功完成Reducers后不更新状态

如何为我的astro页面中的相同组件自动创建不同的内容?

Chart.js 4.4.2,当悬停在一个数据点上时,如何在工具提示中拥有多个数据点/标签?

简单的PayPal按钮集成导致404错误

Prisma具有至少一个值的多对多关系

我在Django中的视图中遇到多值键错误

如何在 Select 文本时停止Click事件?

用于部分字符串的JavaScript数组搜索

MongoDB中的嵌套搜索

如何在Java脚本中并行运行for或任意循环的每次迭代

在Java脚本中构建接口的对象

表单数据中未定义的数组键

连续添加promise 时,如何在所有promise 都已结算时解除加载覆盖

如何在Web项目中同步语音合成和文本 colored颜色 更改

我如何才能获得价值观察家&对象&S的价值?

在使用JavaScript以HTML格式显示Google Drive中的图像时遇到问题

需要从对象生成列表