我们都知道基于事件循环机制,微任务promise执行是早于setTimeout的,但当这两者发生错误时,setTimeout捕获的比promise更早,以下是代码:
window.onerror = e => {
console.log('=====onerror', e)
}
window.onunhandledrejection = e => {
console.log('=====unhandledrejection', e, e.reason)
}
function Test() {
function cacheTest() {
new Promise((resolve, reject) => {
reject('promiseError')
}).catch(e => {
console.log('start throw promiseError')
throw e
})
// Promise.reject('promiseError')
setTimeout(() => {
console.log('start throw setTimeoutError')
throw new Error('setTimeoutError'
)}, 0)
console.log('start throw syncError')
throw new Error('syncError')
}
return (
<div id="test-performance" onClick ={cacheTest}>
Test Insight:Cache Exception
</div>
)
}
ReactDOM.render( <Test/>, document.getElementById('root'))
执行结果如下:
但当将setTimeout更改为setTimeout1时一切结果就符合预期了
setTimeout(() => {
console.log('start throw setTimeoutError')
throw new Error('setTimeoutError'
)}, 1)
执行结果如下:
这是否时由于setTimeout0存在某种特殊机制导致的?
这个问题,我同步提到了stackoverflow,有该社区的大佬也欢迎围观解答:
https://stackoverflow.com/que...
补充相关官方文档:
- 运行时脚本异常:https://html.spec.whatwg.org/...
- promise异步脚本异常:https://html.spec.whatwg.org/...
- 事件循环机制:https://whatpr.org/html/4288/...
啊这?
不是先输出了
start throw promiseError
,然后是
start throw setTimeoutError
吗?最后的几个不都是你又去使用
throw
抛出的异常吗?这些异常没有被
catch
,所以会去执行onerror
和unhandledrejection
事件啊。如果你说的是为什么
.catch
抛出的异常会比setTimout
抛出的异常输出的晚,主要是你的这个异常抛出没有被捕捉,是通过unhandledrejection
来捕捉的。如果给这个异常抛出添加上catch
就会是一致的结果了。以下是添加好异常捕捉之后的前后对比,希望对你有用。

那你肯定要问为什么
unhandledrejection
的输出会比onerror
晚,那我就不清楚了。你得去看ECMA
制定的规范以及浏览器内核的具体实现了。EventSource.onerror - Web API 接口参考 | MDN
unhandledrejection - Web API 接口参考 | MDN