关于这段代码片段执行顺序的问题

Questions about the order of execution of this code snippet

所以我最近一直在阅读关于 Javascript promises 的教程。

这里有一个例子用来解释宏任务队列(即事件循环)和微任务队列。

let promise = Promise.reject(new Error("Promise Failed!"));
promise.catch(err => alert('caught'));

// no error, all quiet
window.addEventListener('unhandledrejection', event => alert(event.reason));

它说因为 promise.catch 捕获了最后一行的错误,事件处理程序永远不会到达 运行。我能理解这一点。但后来他稍微调整了这个例子。

let promise = Promise.reject(new Error("Promise Failed!"));
setTimeout(() => promise.catch(err => alert('caught')));

// Error: Promise Failed!
window.addEventListener('unhandledrejection', event => alert(event.reason));

这次他说事件处理程序将首先 运行 并捕获错误,然后 之后 promise.catch 最终捕获错误。

第二个例子我不明白的是,为什么事件处理程序运行在promise.catch之前?

我的理解是,

  1. 第一行,我们首先遇到一个promise,我们把它放到微任务队列中。
  2. 第二行,我们有一个setTimeout,我们把它放到宏任务队列中,
  3. 第三行,我们有一个事件处理程序,我们将处理程序放在宏任务队列中等待被触发

那么,因为microtask的优先级高于macrotask。我们运行 承诺第一。之后,我们将宏任务队列中的第一个任务出队,即 setTimeout。所以根据我的理解,错误应该被 setTimeout.

里面的函数捕获

请指正。

你对步骤 3) 的看法是错误的。处理程序将同步添加。然后微任务队列得到 运行,promise 被拒绝。由于尚未添加 .catch 处理程序,因此抛出未处理的拒绝。

而且我认为您在 添加回调时 执行回调时 之间混为一谈。考虑这种情况:

  (new Promise).then(function callback() { });

回调将同步添加,但永远不会被调用,因为承诺永远不会解决。在这种情况下:

  Promise.resolve().then(function callback() { });

回调再次被同步添加,但 promise 解析发生在微任务中,因此回调将在 a tick 后执行