JavaScript是一门单线程语言,即一次只能处理一件事情。但是,JavaScript中有很多异步处理机制。了解JavaScript中的执行机制(Event Loop、宏任务和微任务),对于理解异步处理机制,以及优化代码执行效率非常重要。
Event Loop
Event Loop是JavaScript中执行的机制,它是一个循环处理异步任务的过程。它会检查是否有需要执行的任务,以及这些任务是宏任务还是微任务,来安排何时执行它们。
每个Event Loop都有一个消息队列,用于存储待执行的宏任务和微任务。当事件被添加到队列时,Event Loop总是按照以下顺序处理队列中的任务:
- 执行当前宏任务中的同步任务;
- 执行微任务队列中的任务,直到队列为空;
- 取出下一个宏任务并执行;
- 回到2。
宏任务和微任务
宏任务是一些较大的任务,如setTimeout、setInterval、ajax等等。它们被添加到宏任务队列中,等待Event Loop处理。宏任务总是会在微任务之前执行。
微任务是一些较小的任务,如Promise的then和catch方法,MutationObserver等等。它们被添加到微任务队列中,等待Event Loop处理。微任务总是会在下一个宏任务之前执行。
由于宏任务的执行需要一定的时间,因此在一个宏任务中可能会产生多个微任务。当一个宏任务执行结束时,Event Loop会检查微任务队列,将队列中的所有任务依次执行,直到队列为空。然后Event Loop再从宏任务队列中取出下一个任务并执行。
示例
示例1
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
上述代码的执行过程如下:
- 执行console.log('script start'),输出 "script start"。
- 执行setTimeout(...)会将其添加到宏任务队列,等待下一次Event Loop执行时执行。
- 执行Promise.resolve(),会将其添加到微任务队列。
- 执行console.log('script end'),输出 "script end"。
- 当前宏任务执行结束,Event Loop会检查微任务队列,将其队列中的任务依次执行,即输出 "promise1" 和 "promise2"。
- 微任务队列为空,Event Loop将取出下一个宏任务,即执行setTimeout中的回调函数,输出 "setTimeout"。
最终输出结果为:
script start
script end
promise1
promise2
setTimeout
示例2
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
Promise.resolve().then(function() {
console.log('promise2');
});
});
console.log('script end');
上述代码中,添加了一个额外的Promise任务。Promise.resolve()创建了一个新的微任务,它包含了另一个Promise.resolve(),这个Promise.resolve()又创建了一个新的微任务,即:Promise.resolve().then(...)
上述代码的执行过程如下:
- 执行console.log('script start'),输出 "script start"。
- 执行setTimeout(...),添加它到宏任务队列中,等待下一次Event Loop执行。
- 执行Promise.resolve(),添加它到微任务队列中。
- 执行console.log('script end'),输出 "script end"。
- 当前宏任务执行结束,Event Loop会检查微任务队列,发现queue中有一个微任务,输出 "promise1"。
- 执行queue中微任务的Promise.resolve(),在微任务队列中添加一个新的微任务。
- Event Loop检查微任务队列,发现微任务队列中有一个任务,执行它,输出 "promise2"。
- 微任务队列为空,Event Loop继续处理宏任务队列,执行setTimeout中的回调函数,输出 "setTimeout"。
最终输出结果为:
script start
script end
promise1
promise2
setTimeout
通过以上两个示例,我们可以更清晰地了解JavaScript的执行机制,Event Loop、宏任务和微任务的关系,对于理解JavaScript异步处理机制和代码效率优化非常有帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JS的执行机制(EventLoop、宏任务和微任务) - Python技术站