JavaScript 的事件循环、宏任务、微任务
JavaScrtipt 执行顺序
首先,必须要明确,在JavaScript中,所有任务都在主线程上执行。任务执行过程分为同步任务和异步任务两个阶段。异步任务的处理经历两个主要阶段:Event Table(事件表)和 Event Queue(事件队列)。Event Table存储了宏任务的相关信息,包括事件监听和相应的回调函数。当特定类型的事件发生时,对应的回调函数被添加到事件队列中,等待执行。例如,你可以通过addEventListener来将事件监听器注册到事件表上。
执行流程图
事件循环
- 概念:在事件循环中,当主线程执行完当前的同步任务后,会检查事件队列中是否有待处理的事件。如果有,主线程会取出事件并执行对应的回调函数。这个循环的过程被称为事件循环(Event Loop),它由主线程和任务队列两部分组成。主线程负责执行同步任务,而异步任务则通过任务队列进行处理。这种机制保证了异步任务在适当的时机能够插入执行,从而实现了JavaScript的非阻塞异步执行。
- 通俗:事件循环是什么?为什么要有事件循环这个东西?我们都知道JS是单线程的,但是像Ajax,或是DOM事件这种很耗时的操作,需要用并发处理,否则单线程会长时间等待,什么也做不了。而单线程循环就是并发的一种形式,一个线程中只有一个事件循环。而任务队列是用来配合事件循环完成操作的,一个线程可以拥有多个任务队列。
- 执行步骤:
事件循环的tick机制是指事件循环在每个迭代中执行的操作。一个tick通常包括以下步骤:
执行栈清空:JavaScript引擎首先执行执行栈中的所有同步任务。
微任务执行:执行栈清空后,事件循环会执行所有可用的微任务。
宏任务执行:微任务执行完毕后,事件循环会从宏任务队列中取出一个任务并执行。
渲染更新:在浏览器环境中,UI渲染可能会在每个tick之后发生,以更新浏览器界面。
任务队列
任务队列是什么?故名思意,排着任务的队列。所谓任务是WebAPIs返回的一个个通知,让JS主线程在读取任务队列的时候得知这个异步任务已经完成,下一步该执行这个任务的回调函数了。主线程拥有多个任务队列,不同的任务队列用来排列来自不同任务源的任务。任务源是什么?像setTimeout/Promise/DOM事件等都是任务源,来自同类任务源的任务我们称它们是同源的,比如setTimeout与setInterval就是同源的。在ES6标准中任务队列又分为宏观任务队列和微观任务队列
概括
js有两种任务,同步任务和异步任务;异步任务通过任务队列机制来执行代码;任务队列里面分微任务和宏任务。宏任务是由宿主发起的,而微任务由JavaScript自身发起。
微任务:promise process.nextTick() Proxy MutaionObserver
宏任务:setTimeout \ setInterval \ setImmediate \ I/O \ UI交互 、 DOM事件 、 网络请求