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