js事件循环详解

2022-10-05 12:48:38

在js事件循环中,我们需要区分环境,因为javascript可以在node环境和浏览器环境下运行的。所以我们总结js事件循环也从这两个方面去总结。

一、浏览器中js线程

浏览器是一个进程吗?它里面只有一个线程吗?
目前多数的浏览器其实是多进程的,当我们打开一个tab页面时就会开启一个新的进程,这是为了防止一个页面卡死而造成所有页面无法响应。每一个进程中又存在很多的线程,其中包括执行JavaScript代码的线程。
JavaScript的代码执行是在一个单独的线程中执行的,这也就意味着javascript的代码,在同一时刻只能做一件事,如果这个事情比较耗时的话,就意味着当前线程就会被阻塞。
所以真正耗时的操作,实际上并不是由JavaScript线程来执行的,浏览器的每一个进程是多线程的,那么其他线程可以来完成这个耗时的操作,比如网络请求,定时器,我们只需要在特定的时候执行应该有的回调即可。

二、浏览器的事件循环

在这里插入图片描述
上面代码执行过程如下所示:
在这里插入图片描述
因为在执行js代码时,会创建一个新的JavaScript线程,如果遇到定时器等异步操作时,会将该任务交给浏览器的其他线程去执行,当执行完成后,将其回调函数放入任务队列中。js在执行完主线程中的任务后,会从任务队列中提取任务来执行。

三、浏览器中的微任务和宏任务

1、宏任务有:
setTimeOut,setInternal,DOM监听,UI rendering,ajax等。
2、微任务有:
Promise.then的回调Mutation Observer ApIqueueMicrotask等。
3、执行流程
1、首先先执行主程序中的代码
2、然后在执行宏任务队列的代码之前,要先看看微任务队列中是否为空,如果不为空,则将微任务队列中的任务取出执行。
3、在执行宏任务之前,保证微任务队列中的任务为空。

四、浏览器中的事件循环面试题

setTimeout(function(){
  console.log("setTimeOut1")//六newPromise(function(resolve){resolve()}).then(function(){newPromise(function(resolve){resolve()}).then(function(){
      console.log("then4")//八})
    console.log("then2")//七})})newPromise(function(resolve){
  console.log("promise1")//一resolve()}).then(function(){
  console.log("then1")//三})setTimeout(function(){
  console.log("setTimeOut2")//九})



console.log(2)//二queueMicrotask(()=>{
  console.log("queueMicrotask1")//四})newPromise(function(resolve){resolve()}).then(function(){
  console.log("then3")//五})/*
promise1
2
then1
queueMicrotask1
then3
setTimeOut1
then2
then4
setTimeOut2
*/
asyncfunctionasync1(){
  console.log("async1 start")//二awaitasync2()   
  console.log("async1 end")//六}asyncfunctionasync2(){
  console.log("async2")//三}

console.log("script start")//一setTimeout(function(){
  console.log("setTimeOut")//八},0)async1()newPromise(function(resolve){
  console.log("promise1")//四resolve()}).then(function(){
  console.log("promise2")//七})

console.log("script end")//五/*
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeOut
*/

五、node事件循环

在这里插入图片描述
如上图所示,在node环境中通过libuv维护一个事件队列和事件循环,并且通过其中也存在线程池,通过不断轮询线程池中的任务,并将其放入事件队列中,最终再执行线程池中的任务。

六、node事件循环的图解

在这里插入图片描述

七、node中的微任务和宏任务

1、微任务:
next tick queue: process.nexttick
other queue: Promise的then回调函数,queueMicrotask
2、宏任务
timer queue:setTimeOut, setInternal
poll queue: I / O事件
check queue: setImmediate
close queue: close事件
3、在node中执行的顺序

1、next tick microtask queue2、other microtask queue3、timer queue4、poll queue5、check queue6、close queue

八、node事件循环面试题

asyncfunctionasync1(){
  console.log("async1 start")// 2awaitasync2()
  console.log("async1 end")// 9}asyncfunctionasync2(){
  console.log("async2")// 3}

console.log("script start")// 1setTimeout(function(){
  console.log("setTimeOut0")// 11},0)setTimeout(function(){
  console.log("setTimeOut2")// 13},300)setImmediate(()=>{
  console.log("setImmediate")// 12})

process.nextTick(()=> console.log("nextTick1"))// 7async1()  

process.nextTick(()=> console.log("nextTick2"))// 8newPromise(function(resolve){
  console.log("promise1")// 4resolve()
  console.log("promise2")// 5}).then(function(){
  console.log("promise3")// 10})

console.log("script end")// 6/*
script start
async1 start
async2
promise1
promise2
script end
nextTick1
nextTick2
async1 end
promise3
setTimeOut0
setImmediate
setTimeOut2
*/
  • 作者:卖菜的小白
  • 原文链接:https://blog.csdn.net/weixin_47450807/article/details/123131474
    更新时间:2022-10-05 12:48:38