解开 JavaScript 事件循环机制之谜,探寻 Promise面试题背后的真相
2023-12-12 23:16:07
在 JavaScript 的面试中,经常会遇到有关事件循环机制的问题,其中一个经典的题目就是Promise面试题。这道题目的本质是考察你对JavaScript事件循环机制的理解,以及你是否能够灵活运用Promise来解决异步编程中的问题。
这道题目通常会给出这样一个场景:
console.log('script start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
Promise.resolve().then(() => {
console.log('promise1');
});
Promise.resolve().then(() => {
console.log('promise2');
});
console.log('script end');
然后让你预测一下,以上代码的输出顺序是什么。
如果你已经对 JavaScript 的事件循环机制有所了解,那么你可能会猜到正确的输出顺序是:
script start
promise1
promise2
setTimeout
script end
但是,如果你对事件循环机制的理解还不够深入,你可能会得出错误的结论。
为了帮助你理解这道题目的本质,我们先来简单回顾一下 JavaScript 的事件循环机制。
事件循环机制
JavaScript的事件循环机制是一个消息队列,它将要执行的任务存储在队列中,然后依次执行它们。
事件循环机制主要分为以下几个步骤:
- 首先,JavaScript引擎会执行所有的同步任务,也就是那些没有回调函数的任务。
- 当所有同步任务执行完毕后,JavaScript引擎会检查消息队列中是否有任务需要执行。如果有,则取出队列中的第一个任务并执行它。
- 当任务执行完毕后,JavaScript引擎会继续检查消息队列中是否有任务需要执行。如果还有,则取出队列中的第一个任务并执行它。
- 重复步骤2和步骤3,直到消息队列中没有任务需要执行为止。
Promise面试题的解答
现在,我们回到Promise面试题。
首先,JavaScript引擎会执行所有的同步任务,也就是那些没有回调函数的任务。在这个例子中,只有console.log('script start')
是同步任务,因此它会首先执行。
然后,JavaScript引擎会检查消息队列中是否有任务需要执行。在这个例子中,有三个任务在消息队列中等待执行:
setTimeout
任务Promise.resolve().then(() => { console.log('promise1'); })
任务Promise.resolve().then(() => { console.log('promise2'); })
任务
由于setTimeout
任务的延迟时间为0,因此它会先于其他两个任务执行。
setTimeout
任务执行完毕后,JavaScript引擎会再次检查消息队列中是否有任务需要执行。此时,两个Promise
任务都已就绪,因此它们会按照先进先出的原则依次执行。
最后,JavaScript引擎会执行console.log('script end')
这个同步任务。
因此,整个代码的输出顺序就是:
script start
promise1
promise2
setTimeout
script end
结语
通过这道Promise面试题,我们可以看到,JavaScript的事件循环机制是一个非常重要的知识点,它不仅可以帮助我们理解JavaScript的异步编程模型,而且还可以帮助我们解决一些棘手的面试题。