前端时间去面试 面试官问我对EventLoop了解吗?
我猛的想不起来 后来面试官跟我说就是事件循环机制,然后我才想起来
下面我对这次面试问到的事件循环机制(EventLoop)展开说明一下我的理解 以及面试官问的一些实践性问题 (大佬轻喷)
JavaScript中的事件循环(event loop)是一种机制,用于处理异步操作和事件处理。它是JavaScript单线程执行模型的核心部分,允许同时处理多个任务而不会阻塞主线程。
事件循环的基本原理如下:
- JavaScript代码执行开始时,会先处理同步任务(即主线程中的任务),按照顺序执行。
- 当遇到异步任务时,例如定时器、网络请求、事件监听等,它们会被放入事件队列(event queue)中,等待执行。
- 一旦主线程中的同步任务执行完毕,事件循环会检查事件队列,如果队列中存在任务,就会将队列中的第一个任务取出,并放入主线程中执行。
- 异步任务在执行时,如果遇到回调函数或者Promise的resolve/reject操作,这些操作也会被放入事件队列中,等待执行。
- 当主线程中的任务执行完毕后,会再次检查事件队列,如果队列中有任务,就继续执行。这样循环往复,不断处理事件队列中的任务。
这种机制保证了JavaScript的单线程模型,同时允许处理异步操作,避免了阻塞主线程。通过事件循环,JavaScript可以实现诸如定时器、AJAX请求、事件处理等功能,并提供了一种简单而高效的方式处理异步编程。
面试当中面试官经常会问到: 请解释JavaScript中的事件循环机制,并描述事件循环中宏任务(macrotask)和微任务(microtask)之间的区别。 这个题目主要考察面试者对JavaScript中事件循环机制的理解。通过回答这个问题,面试者需要清楚地解释事件循环的基本原理和执行过程,并能够准确描述宏任务和微任务的区别及其执行时机。 回答:事件循环是JavaScript中用于处理异步任务和事件的机制。它确保了JavaScript的单线程执行模型,同时处理异步操作而不会阻塞主线程。
在事件循环中,任务被分为两类:宏任务和微任务。宏任务代表的是较大的任务单元,例如setTimeout、setInterval、I/O操作等。而微任务则是较小的任务单元,例如Promise的回调函数、MutationObserver等。
事件循环的执行过程如下:
- 执行当前的宏任务。
- 检查微任务队列,如果存在微任务,依次执行所有微任务,直到微任务队列为空。
- 更新渲染(如果需要)。
- 从宏任务队列中取出下一个宏任务,如果队列为空,回到步骤2;否则,执行宏任务并回到步骤2。
宏任务和微任务之间的区别在于它们的执行时机和优先级。当主线程执行完一个宏任务后,会检查微任务队列,并在执行下一个宏任务之前清空微任务队列。换句话说,微任务的执行发生在宏任务之间。
微任务具有更高的优先级,它们会在下一个宏任务之前执行完毕。这意味着,如果在当前宏任务中产生了微任务,那么这些微任务会在下一个宏任务之前执行,确保了微任务的及时响应性。
总结起来,事件循环机制通过交替执行宏任务和微任务,实现了JavaScript的异步编程和事件处理能力。
下面说一下面试官问到的实践面试题:
console.log('1');
setTimeout(function() {
console.log('2');
Promise.resolve().then(function() {
console.log('3');
});
});
Promise.resolve().then(function() {
console.log('4');
setTimeout(function() {
console.log('5');
});
});
console.log('6');
让我逐行解释代码的执行过程:
- 首先,执行同步任务,输出1。
- 然后,遇到第一个
setTimeout函数,将其作为宏任务添加到宏任务队列中。由于延迟时间为0,所以这个宏任务会尽快执行。 - 继续执行同步任务,输出6。
- 遇到第一个
Promise.resolve().then,将其注册的回调函数添加到微任务队列中,等待执行。 - 执行第二个
Promise.resolve().then,将其注册的回调函数添加到微任务队列中,等待执行。 - 执行微任务队列中的第一个任务,输出4。
- 继续执行同步任务,遇到第二个
setTimeout函数,将其作为宏任务添加到宏任务队列中。 - 此时,同步任务执行完毕,开始执行微任务队列中的下一个任务。
- 执行微任务队列中的第二个任务,输出2。
- 执行微任务队列中的第三个任务,输出3。
- 最后,执行宏任务队列中的第二个任务,输出5。
综上所述,代码的执行顺序是1、6、4、2、3、5。