关于event loop ,js的事件循环机制

75 阅读3分钟
  • 什么是event loop?

事件循环(event loop)就是 任务在主线程不断进栈出栈的一个循环过程。任务会在将要执行时进入主线程,在执行完毕后会退出主线程。

  • 为什么会有event loop?它解决了什么问题?

我们知道JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。为了协调事件、用户交互、脚本、UI 渲染和网络处理等行为,防止主线程的不阻塞,Event Loop 的方案应运而生。为了解决这个问题,js出现了同步和异步两种任务,两种任务的差异就在于执行的优先级不同。event loop就是对任务的执行顺序做了详细的规范。

  • 同步任务和异步任务

js中的任务主要分为同步任务和异步任务。

同步任务又叫做非耗时任务,指的是在主线程上排队执行的那些任务。只有前一个任务执行完毕,才能执行后一个任务。

异步任务又叫做耗时任务,异步任务由JavaScript 委托给宿主环境进行执行。当异步任务执行完成后,会通知JavaScript 主线程执行异步任务的回调函数。

  • 宏任务和微任务

js中的异步任务分为宏任务和微任务。

常见的微任务有:Promise.then(),.then中的逻辑是微任务;process.nextTick(node环境)。

常见的宏任务有:setTimeout、setInterval、setImmediate(node环境)、xhr(发送网络请求),callback。

  • 任务的执行顺序

1.把同步任务相继加入同步任务队列。

2.把同步任务队列的任务相继加入主线程。

3.待主线程的任务相继执行完毕后,把主线程队列清空。

4.把微任务相继加入微任务队列。

5.把微任务队列的任务相继加入主线程。

6.待主线程的任务相继执行完毕后,把主线程队列清空。

7.把宏任务相继加入宏任务队列。注意:当碰到计时器时,不会立即把计时器里的任务加入宏任务队列,计时器会开始运行,等待计时器运行完成才会把计时器里面的任务加入宏任务队列。

8.把宏任务队列的任务相继加入主线程。

9.待主线程的任务相继执行完毕后,把主线程队列清空。

  • 举个例子

setTimeout(function() {console.log('1');},0) //宏任务
new Promise(function(resolve) {  console.log('2'); //同步任务  resolve()}).then(function() {  console.log('3'); //微任务})
console.log('4'); //同步任务

结果就很明显了,运行顺序是4 2 3 1

  • 进阶
console.log(1)
setTimeout(function() {  console.log(2)  new Promise(function(resolve) {    console.log(3)    resolve()  }).then(function() {    console.log(4)  })},3000)
new Promise(function(resolve) {  console.log(5)  resolve()}).then(function() {  console.log(6)})
setTimeout(function() {  console.log(7)  new Promise(function(resolve) {    console.log(8)    resolve()  }).then(function() {    console.log(9)  })},2000)
console.log(10)
setTimeout(function() {  console.log(11)  new Promise(function(resolve) {    console.log(12)    resolve()  }).then(function() {    console.log(13)  })},0)
// 1 5 10 6 11 12 13 7 8 9 2 3 4

你答对了吗?

  • 结语

    祝看这篇文章的小伙伴们技术越来越好。