深入了解事件js事件循环机制

2018-06-26  本文已影响17人  MenChem

前端领域现在越来越庞大,学习的时候总是一些很零散的东西。感觉不到自己的进步,但是不管怎么学,支撑这些东西的背后还是需要对js的基础有很深入的了解,而时间循环机制(Event Loop)是其中最关键的知识点之一。

在网上查阅很多资料,但大都看的云里雾里,但是在看到这篇文章的讲解感觉就清楚了很多(https://www.jianshu.com/p/12b9f73c5a4f

javascript最大的特点是单线程,在这个线程中拥有唯一一个事件循环

javascript在代码的执行过程中,除了依靠函数调用栈来搞定函数的执行顺序,还依靠任务队列(task queue)来执行另外一些代码。

在一个线程中,事件循环是惟一的,但是队列人物可以拥有多个,人物队列分为宏任务(macro-task)和微任务(micro-task),在最新的标准中,被称为task和jobs。

宏任务(macro-task)大概包括: script代码 , setTimeout , setInterval , setImmediate , I/O , UI rendering

微任务(micro-task)大概包括: process.nextTick , Promise , Object.observe(已废弃) , MutationObserver(html5新特性)

事件循环的顺序决定了javascript代码的执行顺序。它从script开始第一次循环,之后全局上下文进入函数调用栈。知道调用栈清空,然后执行所有的的微任务(micro-task)。当所有可执行的微任务(micro-task)执行完毕之后。循环再次从宏任务(macro-task)开始,找到其中一个任务队列执行完毕,然后再执行所有的微任务(micro-task),这样一直循环下去。

其中每一个任务的执行,无论是宏任务(macro-task)还是微任务(micro-task),都是借助函数调用栈来完成。

通过例子了解一下

setTimeout(function(){
  console.log('t1')
}, 0)

new Promise(function(resolve){
  console.log('p1')
  for(var i = 0; i < 100; i++){
    if( i === 99){
      resolve()
    }
    console.log('p2')
  }
}).then(function(){
  console.log('then1')
})

console.log('global1')

通过上面讲解来拆分一下
首先执行script代码,先遇到setTimeout,setTimeout为一个宏任务,那么会将任务分发到它对应的队列中。

到代码setTimeout这里会分发到宏任务列表,暂时不会执行里面的内容

然后继续执行后面的代码,会遇到Promise实例,Promise构造函数中的第一个参数,是在new的时候执行,因此不会进入其他队列,而是直接执行了,而后续的.then则会分发到微任务(micro-task)的Promise队列中去。继续执行最后输出global1,然后script任务就执行完毕了。


输出p1,p2,.then进入对应队列,最后输出global1

当script执行完毕后开始执行所有可执行的微任务,微任务只有一个then,因此直接执行,直接输出then1

当所有微任务(micro-task)执行完毕后,第一轮循环就结束了。这个时候开始第二轮循环,第二轮循环依然从宏任务(macro-task)开始。


这个时候我们发现宏任务中还有一个srtTimeout等待执行

然后直接执行setTimeout,输出t1,这个时候宏任务和微任务队列都没有任务了,所以代码就不会再输出其他东西了。

最后输出结果是
上一篇 下一篇

猜你喜欢

热点阅读