问题描述
如果一个promise创建了一个新的微任务回调,并且在处理下一个宏任务之前已解决了所有微任务,为什么不保证promise会阻塞事件循环?
这里是一个答案,解释了诺言就像事件通知系统一样,显然这是正确的,因为诺言不会阻塞,这就是重点:
Do Javascript promises block the stack
但是要清楚一点,如果将回调添加到微队列中,并且必须清空该队列以继续执行下一个宏任务,为什么它不阻塞?
解决方法
它确实会阻止,例如您可能会在微任务检查点被阻止。
const block_loop = () => Promise.resolve().then( block_loop );
document.getElementById('btn').onclick = evt => {
if( confirm("this will block this page") ) {
block_loop();
}
};
<button id="btn">block the event loop</button>
This frame will get blocked.
此示例不会阻塞任务的来源,但是由于从微任务端点排队的微任务将排队在要清空的同一微任务队列中,因此实际上您将陷入无尽的循环,并且事件循环将无法处理任何将来的任务。
微任务也是任务,它们的处理本身也会像其他任何任务一样阻塞事件循环:
const block_loop = () => {
const start = performance.now();
while( performance.now() - start < 10000 ) {
}
};
document.getElementById('btn').onclick = evt => {
if( confirm("this will block this page for 10s") ) {
Promise.resolve().then( block_loop );
}
};
<button id="btn">block the event loop</button>
This frame will get blocked.