js的macrotask和microtask

  • js每次事件循环只从macrotask中读取一个并任务执行,同一个事件循环会把microtask中的任务执行完毕并且先于macrotask

为什么要将数据更新的处理函数放在microtask队列中

  • 两个macrotask中可能穿插着ui重渲染,所以在microtask中在ui重渲染之前把所有的数据更新,一次渲染就能得到最新的DOM结构,减少开销;所以优先把更新数据的操作放在microtask队列中,批处理更新

vue中的nextTick的实现

  • vue中的nextTick根据浏览器的特性封装,优先级如下

    • vue@2.5+ Promise > setImmediate > MessageChannel > setTimeout。
    • vue@<2.5 Promise > MutationObserver > setTimeout

      • Promise

        • 以上函数只有Promise是将回调放进microTak队列中,所以是最优方案,只有在Promise不存在的情况下才会走其他方法。
      • 将setTimeout放到优先级的最后的原因:

        • setimeout中的回调并不是放在microtask而是macrotask中,对于重渲染是有开销的;
        • 在回调之前要不断做超时检查, 用setTimeout最快也是4ms发以后调用回调
        • 虽然setTimeout不是最优方案但是可作为兼容性最好的方案
      • MessageChannel 和 MutationObserver

        • 由于兼容性问题,vue2.5开始抛弃了MutationObserver
        • MessageChannel拥有port1,port2两个属性,让其中一个port监听onMessage,另一个port发送消息即可,不需要像setTimeout做超时检测,它作为非ie浏览器兼容方案。
        • onMessage回调会被注册为macroTask。
      • setImmediate也是将回调函数放进marcoTak中,优点是不需要做超时检测,目前只有ie浏览器实现。

本文固定链接: http://www.js-code.com/vue-js/vue-js_25102.html