这些天我一直在阅读有关JavaScript promise的教程。
以下是其中一个例子,用于解释宏任务队列(即事件循环)和微任务队列。
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
之前运行?
我的理解是:
- 第一行,我们遇到一个 Promise,并把它放在微任务队列中。
- 第二行,我们有一个
setTimeout
,我们把它放在宏任务队列中。 - 第三行,我们有一个事件处理程序,我们把处理程序放在宏任务队列中等待被触发。
因为微任务的优先级高于宏任务,所以我们首先运行 Promise。之后,我们从宏任务队列中出队第一个任务,即 setTimeout
。所以根据我的理解,错误应该由 setTimeout
内部的函数捕获。
请纠正我。
返回:
这里需要更正的是,在第二个例子中,事件处理程序确实在 promise.catch
之前运行,因为事件处理程序是宏任务而不是微任务。因此,事件处理程序将在 Promise 执行完之后立即执行,但在 setTimeout
函数之前。