当前位置: 首页 > Web前端 > JavaScript

一直被问到事件循环,今天终于明白了!

时间:2023-03-27 14:01:58 JavaScript

JavaScript执行在浏览器中是单线程的。如何在单线程中实现异步操作?答案是事件循环。事件循环(EventLoop)浏览器通过事件循环处理事件、用户交互、JS代码执行、渲染、网络请求等。通常有两种事件循环,一种是Window事件循环,另一种是Worker事件循环。由于它们的核心工作原理相同,本文只讨论Window事件循环。事件循环,首先是一个循环,每个循环周期都会执行一些代码,一个循环周期称为tick。while(eventLoop.waitForTask()){eventLoop.processNextTask()}一个事件循环有一个或多个任务队列。每个任务队列都是一个有序的任务列表。可以理解为一段要执行的代码,或者浏览器要执行的一个动作,比如发送事件,解析HTML等。网页和浏览器本身的用户界面程序运行在同一个线程中并共享相同的事件循环。这个线程是主线程。除了运行网页本身的代码外,它还负责收集和调度用户和其他事件,以及渲染和绘制网页内容。然后,事件循环驱动浏览器中发生的与用户交互相关的所有事情。执行过程简单来说,事件循环在每个循环中会依次执行以下步骤:1.选择一个任务队列,从队列中取出最前面(最旧)的任务。如果没有更多任务,则跳到步骤3。2.执行获取的任务。3、从微任务(MicroTask)队列中取出微任务执行,直到微任务队列清空。4.更新渲染(调整大小、滚动、动画等)5.回到步骤1。每个时间循环都有一个微任务队列。微任务队列与任务队列非常相似,不同的是每个周期只会执行任务队列中的一个任务,任何在此期间产生的任务只能在下一个周期执行。执行完前置任务后,事件循环逐个执行微任务队列中的每个微任务,直到微任务队列为空。也就是说,microtasks执行过程中新产生的microtasks也会在当前cycle中执行。不同的任务队列可能有不同的优先级。例如,浏览器可能将用户的鼠标和键盘输入(用户交互)任务放在一个任务队列中,而将其他任务放在另一个队列中。在每个循环中,任务从用户交互队列中取出执行,以保证及时响应用户操作。下图显示了一个事件循环循环的执行。任务和微任务任务可以简单理解为一段要执行的JavaScript代码。例如,当