event loop 事件循环

 

js是单线程运行,从上到下逐步执行,js有一个:主线程,还有一个回调队列。在js中,任务分为同步任务和异步任务;

当遇到异步任务(ajax,settimeout等),会先注册异步回调函数,等异步任务执行完的时候,会把异步回调放在一个先进先出的队列里,当主线程执行完毕之后,会读取队列里的异步回调函数,这个不断重复的过程就是 event loop 事件循环。

 

JS的事件循环如图所示,

  1. 在执行主线程的任务时,如果有异步任务,会进入到Event Table并注册回调函数,当指定的事情完成后,会将这个回调函数放到 callback queue 中
  2. 在主线程执行完毕之后,会去读取 callback queue中的回调函数,进入主线程执行
  3. 不断的重复这个过程,也就是常说的Event Loop(事件循环)了

异步任务

js的异步任务,分为宏任务跟微任务、他们之间的区别主要是执行顺序的不同。

在js中

微任务

  • 原生的Promise (new Promise在实例化的过程中所执行的代码都是同步进行的,而then中注册的回调才是异步执行)

  • process.nextTick 

process.nextTick的执行优先级高于Promise

宏任务

  • 整体代码 script
  • setTimeout 
  • setImmediate

setTimeout的执行优先级高于 setImmediate 的

宏任务与微任务的执行过程

在一次事件循环中,JS会首先执行 整体代码 script,执行完后会去判断微任务队列中是否有微任务,如果有,将它们逐一执行完后在一次执行宏任务。如此流程

大体可以这样排序

  整体代码 script  process.nextTick > Promise > setTimeout  > setImmediate 

 

当遇到这种类型的题目 可以先列出4行

 

宏任务

微任务

执行队列

输出

 

以一个题目为例

process.nextTick(() => {
  console.log('a');
  setImmediate(() => {
    console.log('d')
  })
})

setImmediate(() => {
  console.log('b');
  process.nextTick(() => {
    console.log('c')
  })
})

  答案 abcd,解析过程:

一开始 执行 ,js代码放在宏任务 ,此时执行队列为空,微任务为空

宏任务  js代码 

微任务 

执行队列   

输出

所以将宏任务中js代码放在执行队列中   

宏任务  

微任务 

执行队列    js代码 

输出

然后把 nextTick放在微任务中,setImmediate放在宏任务中

宏任务   setImmediate

微任务 nextTick

执行队列   

输出   

当微任务中有任务 则优先微任务 此刻有一个nextick 将他内部的内容进行解读 执行 console.log('a'); 优先输入 再将setImmediate 放入宏任务队列

宏任务   setImmediate  setImmediate(console.log('d'))

微任务 

执行队列  console.log('a'); 

输出  a

执行完执行队列 后,微任务没有任务 则看宏任务setImmediate  中有一个 console.log('b');直接执行 ,然后有一个nextTick放在微任务中

宏任务   setImmediate(console.log('d'))

微任务  nextTick

执行队列  console.log('b');

输出  a  

执行微任务中的nextTick  console.log('c')

宏任务   setImmediate(console.log('d'))

微任务 

执行队列  console.log('c');

输出  a  b c

之后微任务没有任务 继续看宏任务中的setImmediate,输出 d

宏任务   

微任务 

执行队列  console.log('d')

输出  a  b c

所以最后的答案是 abcd

 

实际遇到的问题会比这个更加复杂 ,记住步骤 以及   整体代码 script  process.nextTick > Promise > setTimeout  > setImmediate 执行优先顺序

 

注意点:

new Promise实例化的过程中所执行的代码都是同步进行的,而then中注册的回调才是异步执行 

setTimeout(_ => console.log(4))

new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)
})

console.log(2)

  答案是 1234

 

 

 

 

这里有一个博客  你可以很清晰得看到 运行的顺序  十分推荐 看这个

https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/?utm_source=html5weekly

 

 参考的相关博客   相关博客 

找到了一个 博客讲的很有意思 放在这里方便以后查看 

 之后会继续补充 

posted @ 2020-09-10 20:41  明媚下雨天  阅读(228)  评论(0编辑  收藏  举报