一篇文章让你搞清楚JavaScript事件循环
什么是事件循环?
JavaScript是一门单线程语言,它有一个主线程执行环境(即全局上下文环境),主线程会按照代码的顺序依次执行。然而,由于JavaScript需要处理UI操作、网络请求、定时器等事件,而这些事件需要等待的时间可能非常长,如果按照阻塞式的方式等待,就会影响用户体验。因此,JavaScript采用异步执行和事件循环机制来解决这个问题。
事件循环是一种执行模型,用于处理JavaScript中异步代码的执行顺序。JavaScript通过异步机制将带有回调函数的异步任务放在任务队列中,主线程开始执行同步任务,当同步任务结束后,JavaScript引擎开始轮询任务队列,如果任务队列中有待处理任务,就将它们推送到主线程中执行,主线程继续执行一遍事件循环后回到等待下一个任务的状态。这就是事件循环的基本流程。
任务队列
常见的任务队列主要有三个:主线程任务队列、微任务队列和宏任务队列。
主线程任务队列
主线程任务队列是一个FIFO队列,主要存储异步任务的回调函数。当主线程执行完当前的同步任务后,会检查主线程任务队列中是否有待处理的函数,如果有,那么主线程将会将这些任务加入到主线程任务队列的末尾,然后处理这些任务。
微任务队列
微任务队列是用于存储带有回调函数的异步任务,这些任务通常是由Promise.then()、请求动画帧和queueMicrotask()方法添加的。当JavaScript执行完所有同步任务和在主线程任务队列中发现了异步任务后,JavaScript引擎先会检查是否存在微任务队列。如果存在微任务,那么它们将会被依次处理,直到微任务队列为空为止。
宏任务队列
宏任务队列用于存放那些需要异步执行的回调函数。主线程任务队列中的回调函数通常会被添加到宏任务队列,此外,像setTimeout()、setInterval()和I/O操作等也会被添加到宏任务队列中。当主线程任务队列中的任务全部执行完毕并且微任务队列中所有任务也执行完毕后,JavaScript引擎会去检查宏任务队列,如果有宏任务,则将队列中的第一个任务加入到主线程任务队列中执行,如果宏任务队列为空,则继续等待新的宏任务的加入。
示例:setTimeout和Promise
接下来,我们使用两个示例来展示事件循环是如何工作的。
示例一:setTimeout
console.log('main1')
setTimeout(() => {
console.log('timeout')
}, 0)
console.log('main2')
上面的代码会先输出‘main1’,接着输出‘main2’,最后输出‘timeout’。这是因为setTimeout()是一种宏任务,它会被添加到宏任务队列中等待执行,而当前任务队列中的两个console.log()函数是同步的,它们会在当前的任务队列被执行完毕后立即执行。当前任务队列执行完毕后,JavaScript引擎会检查宏任务队列中是否有待处理的任务,如果有,则将它们添加到主线程任务队列中执行。
所以,上面的代码输出的顺序是先输出同步任务中的‘main1’和‘main2’,然后由于setTimeout的回调函数处于宏任务队列中,所以在当前任务队列执行完毕后,JavaScript引擎会去宏任务队列中查找任务,由于宏任务队列中只有一个任务(setTimeout的回调函数),所以将它加入主线程任务队列中执行,在主线程任务队列中执行的时候才输出‘timeout’。
示例二:Promise
console.log('main1')
Promise.resolve().then(() => {
console.log('promise')
})
console.log('main2')
上面的代码会先输出‘main1’,接着输出‘main2’,最后输出‘promise’。当前任务队列中的console.log()函数是同步的,它们会在当前的任务队列被执行完毕后立即执行,而Promise.resolve().then()方法是一种添加微任务的方式,它会将回调函数添加到微任务队列中等待执行,等整个当前任务队列执行完毕后,JavaScript引擎会去检查微任务队列中是否有待处理任务,如果有,则会依次执行这些微任务。
在上述代码中,当main2执行完毕后,JavaScript引擎会查找微任务队列,并发现存在微任务,然后依次执行微任务队列中的回调函数,于是输出‘promise’。
到此为止,我们已经基本了解了JavaScript事件循环的执行过程以及任务队列的相关概念和使用方法。在实际开发中,了解事件循环的执行过程能够帮助我们更好地理解异步编程模型,从而更好地掌握JavaScript的异步机制。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一篇文章让你搞清楚JavaScript事件循环 - Python技术站