1、什么是事件循环
在前端开发中,事件循环(Event Loop)是JavaScript运行时环境(如浏览器)用来处理异步任务和回调的一种机制。由于JavaScript是单线程的,这意味着它一次只能处理一个任务。然而,为了处理如用户交互、网络请求、定时器回调等异步事件,事件循环机制被引入。
事件循环的工作原理可以概括为以下几个步骤:
执行栈:当JavaScript代码开始执行时,它首先会进入一个执行栈。同步代码会按照顺序依次执行,直到执行栈为空。
任务队列:当遇到异步任务(如setTimeout、setInterval、AJAX请求、Promise等)时,这些任务不会被立即执行,而是被放入一个或多个任务队列中等待。这些队列分为宏任务队列(macrotask queue)和微任务队列(microtask queue)。
宏任务(Macrotasks):包括script(整体代码)、setTimeout、setInterval、setImmediate(Node.js环境)、I/O、UI渲染等。
微任务(Microtasks):包括Promise的回调、process.nextTick(Node.js环境)、MutationObserver等。
事件循环:当执行栈为空时,事件循环会检查微任务队列。如果微任务队列中有任务,它会取出一个微任务并执行,直到微任务队列为空。然后,事件循环会检查宏任务队列,并取出一个宏任务来执行。这个过程会不断重复,形成一个循环。
异步任务的回调:当异步任务完成(如定时器到达指定时间、网络请求返回数据)时,相应的回调函数会被放入任务队列中,等待事件循环在合适的时机执行。
通过事件循环机制,JavaScript能够高效地处理异步任务和回调,而不会阻塞主线程。这使得前端应用能够响应用户交互、处理网络请求等异步操作,同时保持界面的流畅性。
2、为什么要有事件循环这种处理方式
因为js是一门单线程的语言,所有的代码任务会被放入执行栈中顺序执行。然而,当我们遇到异步的任务处理时,如果只是由js的执行栈来执行,将会不可避免地漏掉异步任务。但是对于浏览器(宿主环境)而言,是可以支持多线程任务处理的,
3、同步代码和异步代码
console.log(1)
setTimeout(function(){
console.log(2)
},2000)
console.log(3)
以上代码为例,同步代码包括
console.log(1)
console.log(3)
异步代码包括
setTimeout(function(){
console.log(2)
},2000)
通常地,我们将 setTimeout、setInterval、Ajax/Fetch、事件绑定 等 这一类需要时间来执行的代码都叫做异步代码;
同步代码:立即放入JS引擎(JS主线程)执行,并在原地等待结果;
异步代码:先放入宿主环境(浏览器/Node),不必原地等待结果,并不会阻塞主线程继续往下执行,异步结果在将来执行;
4、总结
1、JS是单线程,防止代码阻塞,我们把代码(任务):同步和异步;
2、同步代码给JS引擎执行,异步代码交给宿主环境来执行;
3、同步代码放入到执行栈中,异步代码等待时机成熟(例如事件触发,定时器等待完成)送入任务队列排队;
4、执行栈执行完毕,会到任务队列中看是否有异步任务,有就送到执行栈执行,反复循环查看执行,这个过程叫做事件循环 eventLoop;