Event Loop

作者: 马建阳 | 来源:发表于2018-02-21 12:41 被阅读5次

我们先来看一道题目
我们知道Promise是异步的,而定时器接口也是异步的。那么它们哪个先执行?

button.onclick = function(){
   setTimeout(function(){console.log(1),0})
   console.log(2)
   x().then(success)
   console.log(3)
   function x(){
      return new Promise(function(resolve,reject){
          console.log(4)
          resolve()
         })
     }
  function success(responseText){console.log(5)}
}

注:promise的理解:先执行function(resolve,reject){}函数,再return new Promise(),reject和resolve分别是钩子,勾起内容,给then和catch当内容使用。
这里面就涉及到js的运行机制event loop了。
简单点说:JS只有一个主线程,主线程执行完执行栈的任务后去检查异步的任务队列,如果异步事件触发,则将其加到主线程的执行栈去执行。
可是这根本没用啊,setTimeout和 Promise都是异步的,你不是废话吗,wait...

以上的事件循环过程是一个宏观的表述,实际上因为异步任务之间并不相同,因此他们的执行优先级也有区别。不同的异步任务被分为两类:微任务(micro task)和宏任务(macro task)。

以下事件属于宏任务:

setInterval()
setTimeout()
以下事件属于微任务

new Promise()
new MutaionObserver()
当当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。

因此虽然then和setTimeout都是属于‘下一批’执行的。但Promise比setTimeout稍微快一点。
Promise的“下一批”属于microTask,定时器的”下一批”属于macroTask。这两个“下一批”并不是”同一批”。

所以控制台打印的结果为

2
4
3
5
1

这让我联想到vue的nextTick,和react的setState,这两个都设及到了异步更新队列,让我们来看一下

什么时候需要用的Vue.nextTick()
1.你在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中。原因是什么呢,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。

2.在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。
[promise](https://shenfeng1945.github.io/2017/08/19/%E6%B5%85%E8%B0%88Promise%E5%AF%B9%E8%B1%A1/#more
eventloop
macro task与micro task
nextTick

相关文章

网友评论

    本文标题:Event Loop

    本文链接:https://www.haomeiwen.com/subject/yqsntftx.html