javascript系统系列:浅析js中的浏览器循环事件(eventLoop)

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

大家好,我是前端岚枫,今天主要跟大家分享我整理的浏览器事件循环eventLoop相关:eventloop, 微任务、宏任务等,此方面内容在我们的工作中常用到, 也是大厂面试经常提问的问题,希望下面文章对大家有所帮助。

event loop

event loop就是异步回调的实现原理

  • 同步代码,一行一行放在Call Stack 执行
  • 遇到异步,会先“记录”下,等待时机(定时、网络请求等)
  • 时机到了,就移动到Callback Queue
  • 如Call Stack为空(即同步代码执行完)Event Loop开始工作
  • 轮询查找Callback Queue ,如有则移动到Call Stack 执行
  • 然后继续轮询查找(永动机一样)

1. 浏览器的进程

  • 每一个页卡都是进程(互不影响)
  • 浏览器也有一个主进程(用户界面)
  • 渲染进程 每个页卡里 都有一个渲染进程(浏览器内核)
  • 网络进度(处理请求)
  • GPU进程 3d绘制
  • 第三方插件的进程

进程是计算机调度基本单位

2. 渲染进程(包含着多个线程)

  • GUI渲染进程(渲染页面的)
  • js引擎线程,他和也门渲染时互斥
  • 事件触发线程,独立的线程 EventLoop
  • DOM事件也使用回调,基于event loop,事件click、setTimeout、ajax也是一个独立线程

3. 宏任务、微任务

  • 宏任务 宿主环境提供的异步方法 都是宏任务 script 、ui 渲染、setTimeout , setInterval , Ajax,DOM事件
  • 微任务 语言标准提供promise async/await mutationObserver
  • 微任务执行时机比宏任务要早

image.png

document.body.style.background = 'blue'
console.log(1)
setTimeout(()=>{
  console.log(2)
  document.body.style.background = 'red'
},0)
console.log(3)
复制代码
// es6内部是一个微任务
Promise.resolve().then(()=>{
	console.log('Promise1')
  setTimeout(()=>{
  	console.log('setTimeout2')
  })
})
setTimeout(()=>{
  console.log('setTimeout1')
  Promise.resolve().then(()=>{
  	console.log('Promise2')
  })
}, 0)
// Promise1
// setTimeout1
// Promise2
 //setTimeout2
复制代码
//async 返回的是一个promise generator +co
// await => yield 如果产出的是一个promise会调用这个promise.then方法
async function async1(){
	console.log('async1 start')
  //浏览器识别async + await await后面跟的是promise的话默认就会直接调用这个promise的then方法
  await async2();
  console.log('async1 end')
}
async function async2(){
	console.log('async2');
}
console.log('script start')
setTimeout(()=>{
  	console.log('setTimeout')
  }, 0)
async1();
new Promise(function(resolve){
	console.log('promise1')
  resolve()
}).then(function(){
	console.log('promise2')
})
console.log('script end')


/**
默认执行 script start ,async1 start
微任务队列【async1 end, promise2】
宏任务队列 【 setTimeout】
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
**/
复制代码

4. event loop和 DOM渲染

  • 再次回归一遍event loop的过程
  • JS是单线程的,而且和DOM渲染共用一个线程
  • JS执行的时候,得留一些时机供DOM渲染
  • 每次Call Stack清空(即每次轮询结束),即同步任务执行完
  • 都是DOM重新渲染的机会,DOM结构如有改变则重新渲染
  • 然后再去触发下一次Event Loop

◆ 宏任务:DOM渲染后触发,如setTimeout ◆ 微任务: DOM渲染前触发,如Promise ​

原因

  • 微任务是ES6语法规定的
  • 宏任务是由浏览器规定的

程序员石磊

猜你喜欢

转载自juejin.im/post/7031360903442513951