JS事件循环

JS事件循环

1、所有任务都在主线程上执行,主线程执行任务的时候会形成执行栈

2、在主线程之外还存在一个任务队列,系统会把异步任务会放入任务队列中,然后继续执行主线程任务

3、执行栈中所有的任务执行完毕之后,系统会从任务队列中读取任务,已经结束等待状态的异步任务会进入执行栈,恢复执行

主线程重复上面三步的过程就是事件循环。

队列分为宏任务和微任务。

宏任务:全局script、setTimeout、setInterval、setImmediate、I/O、UI rendering。setTimeout实际上是个任务分发器。

微任务:process.nextTick、promise.then()并且process.nextTick()的优先级大于promise.then()。

第一轮事件循环是从script开始的,在script执行过程中会产生宏任务和微任务(视具体的代码情况而定)。宏任务和微任务会被分别放入对应的任务队列当中。在第一轮事件循环的宏任务执行完成之后会执行本轮循环产生的微任务,微任务执行完成之后会被清空进入下一轮事件循环。下一轮事件循环又是从宏任务开始,宏任务执行完成之后会执行本轮产生的微任务,以此类推,直至结束。在本轮产生的宏任务会被放到下一轮事件循环时执行。

举个例子:

async function async1() {
  console.log('async1 start')

  await async2()

  console.log('async1 end')

}

async function async2() {

  console.log('async2')

}

console.log('script start')

setTimeout(function () {

  console.log('settimeout')

})

async1()

new Promise(function (resolve) {

  console.log('promise1')

  resolve()

}).then(function () {

  console.log('promise2')

})

console.log('script end')

  上述代码一开始时执行 

console.log('script start') 打印‘script start’
然后执行到setTimeout时会产生一个宏任务(暂且叫setTimeout1),此时产生的宏任务会在下一轮事件循环开始时执行,处于暂时被挂起状态。
接着执行async1()方法,打印“async1 start”,再往下执行await async2()会打印“async2”,此时async2()返回的是个promise,后面的内容相当于是then里面的内容,是个微任务,暂时挂起。
接着执行new Promise,new Promise参数里面的内容会先执行打印“promise1”,then里面的内容也是个微任务,会被添加到上一步产生的微任务队列后面,等待执行,也是挂起状态。
接着执行“console.log('script end')”,打印“script end”。第一轮事件循环宏任务结束,开始执行微任务,先执行“console.log('async1 end')”,因为这个处在微任务队列的最前面,
接下来执行promise1后面的then,打印“promise2”,至此第一轮事件循环就结束了。
进入下一轮事件循环,从宏任务开始执行,先执行setTimeout1打印“settimeout”,后面没有任务队列,所有的都执行完成。
所以打印的顺序是:
script start
async1 start
async2
promise1
script end
async1 end
promise2
settimeout

 

posted @ 2022-07-26 14:18  闯入码途的水产人  阅读(176)  评论(0编辑  收藏  举报