解释 setTimeout 和 catch 处理程序的执行顺序
Explain this order of execution of setTimeout and catch handlers
我对定时器函数、微任务和事件监听器的执行顺序有疑问:
let promise = Promise.reject("Err@!");
setTimeout(() => {
promise.catch(er => console.log(er, "Caught !")); // (1)
});
window.addEventListener('unhandledrejection', event => console.log("Unhandled Rejection !", event.reason)); // (2)
// Output
// >> Unhandled Rejection ! Err@!
// >> Err@! Caught !
在此,被拒绝的 promise 在被 setTimeout
中的 .catch()
捕获之前被 Unhandled Rejection
事件捕获,原因是:
An "unhandled rejection" occurs when a promise error is not handled at
the end of the microtask queue (https://javascript.info/microtask-queue#unhandled-rejection)
现在考虑另一种情况:
let promise = Promise.reject("Err@!");
setTimeout(() => { // (1) ,gets called first
setTimeout(function () { // (3) , gets called at last , (after (2))
promise.catch(er => console.log("caught ", er ))
})
});
setTimeout(function () { // (2) , gets called after (1)
window.addEventListener('unhandledrejection', event => console.log("Unhandled Rejection !", event.reason));
})
// Output
//>> caught Err@!
在此,promise 被嵌套 setTimeout
中的 catch
处理程序捕获,即使在第二个 setTimeout
中,微任务队列为空并且仍未处理被拒绝的 promise通过 window 事件侦听器...
为什么会这样?
当 promise 拒绝(未被处理)时,unhandledrejection 处理程序尚未附加,因此它不会处理该案例。您可以随时附加 .catch
和 .then
处理程序,如果 Promise 已经 resolved/rejected,它们将立即触发(在微任务中)。
// first example
1) synchronous execution
- promise rejected
- timeout set
- unhandledrejection event handler attached
2) microtasks
- promise rejects
3) macrotask
- timeout triggers
-> .catch handler gets attached
4) microtasks
.catch gets executed
// second example
1) synchronous execution
- timers get attached
- promise rejects
2) microtasks
- promise rejected
3) macrotasks
- timer 1 done
- timer 3 started
- timer 2 done
- unhandledrejection handler added
我对定时器函数、微任务和事件监听器的执行顺序有疑问:
let promise = Promise.reject("Err@!");
setTimeout(() => {
promise.catch(er => console.log(er, "Caught !")); // (1)
});
window.addEventListener('unhandledrejection', event => console.log("Unhandled Rejection !", event.reason)); // (2)
// Output
// >> Unhandled Rejection ! Err@!
// >> Err@! Caught !
在此,被拒绝的 promise 在被 setTimeout
中的 .catch()
捕获之前被 Unhandled Rejection
事件捕获,原因是:
An "unhandled rejection" occurs when a promise error is not handled at the end of the microtask queue (https://javascript.info/microtask-queue#unhandled-rejection)
现在考虑另一种情况:
let promise = Promise.reject("Err@!");
setTimeout(() => { // (1) ,gets called first
setTimeout(function () { // (3) , gets called at last , (after (2))
promise.catch(er => console.log("caught ", er ))
})
});
setTimeout(function () { // (2) , gets called after (1)
window.addEventListener('unhandledrejection', event => console.log("Unhandled Rejection !", event.reason));
})
// Output
//>> caught Err@!
在此,promise 被嵌套 setTimeout
中的 catch
处理程序捕获,即使在第二个 setTimeout
中,微任务队列为空并且仍未处理被拒绝的 promise通过 window 事件侦听器...
为什么会这样?
当 promise 拒绝(未被处理)时,unhandledrejection 处理程序尚未附加,因此它不会处理该案例。您可以随时附加 .catch
和 .then
处理程序,如果 Promise 已经 resolved/rejected,它们将立即触发(在微任务中)。
// first example
1) synchronous execution
- promise rejected
- timeout set
- unhandledrejection event handler attached
2) microtasks
- promise rejects
3) macrotask
- timeout triggers
-> .catch handler gets attached
4) microtasks
.catch gets executed
// second example
1) synchronous execution
- timers get attached
- promise rejects
2) microtasks
- promise rejected
3) macrotasks
- timer 1 done
- timer 3 started
- timer 2 done
- unhandledrejection handler added