eventloop(事件循环机制)

在开始讲事件循环前,先对一些概念进行梳理:参考链接 

浏览器常驻线程:

  • 渲染引擎线程:顾名思义,该线程负责页面的渲染
  • js引擎线程:负责js解析和执行
  • 定时触发器线程:处理定时事件,比如setTimeout,setInterval
  • 事件触发线程:处理DOM事件
  • 异步http请求线程:处理http请求

js:单线程语言

同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务,如果上一个任务响应时间长则会拖延整个程序的进行。

异步任务:不进入主线程,而进入任务队列中的任务,只有任务队列通知主线程,某个异步任务可以执行了,这个任务才会进入主线程执行。

任务队列(task queue):事件的队列,IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈"了。主线程读取"任务队列",就是读取里面有哪些事件。

 js中有两类任务队列:宏任务队列和微任务队列。宏任务队列可以有多个,微任务队列只有一个。

  • 宏任务:script( 整体代码)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 环境)
  • 微任务:Promise、MutaionObserver、process.nextTick(Node.js 环境)

 

代码执行优先级:

 

同步代码(宏任务) > process.nextTick > Promise(微任务)> setTimeout(fn)、setInterval(fn)(宏任务)> setImmediate(宏任务)> setTimeout(fn, time)、setInterval(fn, time),其中time>0

 


 

 有一道题如下~

setTimeout(()=>console.log('a'),0)


var p = new Promise((resolve) => {
console.log('b')
resolve()
})


p.then(()=>console.log('c'))
p.then(()=>console.log('d'))


console.log('e')

请输出顺序

 

正确输出顺序为【becda】(选中查看)

 

解析:

settimeout加入宏任务队列

promise实例化部分为同步任务,直接执行,输出b

promise.then为异步任务,且是微任务,加入微任务队列*2

console为同步任务,直接执行,输出e

此时程序中主线程任务已全部执行完,开始读取任务队列中的任务

优先读取微任务队列,输出c,d

然后读取宏任务队列,输出a

 


总结:

 

 

 

同步和异步任务分别进入不同的执行环境,同步的进入主线程,即主执行栈,异步的进入任务队列。主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。 上述过程的不断重复就是我们说的 Event Loop (事件循环)。

 

一篇写得挺好的文章:https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651229977&idx=1&sn=e74d2564a25ade60323ee03f098b9f49&chksm=bd49569d8a3edf8bff6e67a1eff689d1ca26e8289ece27b6cca213250875924a18b3c8abdcd0&scene=21#wechat_redirect


async function func1() {
  console.log(1)
  await func2()
  console.log(2)
}

async function func2() {
  console.log(3)
}

console.log(4)

func1()

setTimeout(()=>{
  console.log(5)
},0)

new Promise((resolve,reject)=>{
  console.log(6)
  resolve()
}).then((res)=>{
  console.log(7)
})

console.log(8)

 // 4,1,3,6,8,2,7,5

posted @ 2020-06-30 16:03  真希  阅读(657)  评论(0编辑  收藏  举报