任务队列(Event Loop)
JavaScript 运行时,除了一个正在运行的主线程,引擎还提供多个任务队列(根据任务的类型,所以有多个)。
首先,主线程会去执行所有的同步任务。等到同步任务全部执行完,就会去看任务队列里面有没有事件回调。如果有,则取出重新进入主线程执行,这时它就变成同步任务了。等到执行完,下一个异步任务再进入主线程开始执行。一旦任务队列清空,程序就结束执行。
异步任务的写法通常是回调函数。一旦异步任务重新进入主线程,就会执行对应的回调函数。如果一个异步任务没有回调函数,就不会进入任务队列,也就是说,不会重新进入主线程,因为没有用回调函数指定下一步的操作。
只要同步任务执行完了,引擎就会一遍又一遍地去检查那些挂起来的异步任务,是不是可以进入主线程了。这种循环检查的机制,就叫做事件循环(Event Loop)
目前JS的主要运行环境有两个——浏览器和Node.js。相比于V8引擎,node 中增加了两种异步方式: process.nextTick() 和 setImmediate()。
Node 规定,process.nextTick()和Promise的回调函数,追加在本轮循环,即同步任务一旦执行完成,就开始执行它们。
而setTimeout、setInterval、setImmediate的回调函数,追加在次轮循环。
任务分为:同步任务,异步任务;异步任务分为微任务和宏任务。
1. this.$nexttick()
vue里的数据变化之后,dom是异步更新的。如果需要获取dom属性,或者需要在dom更新之后执行的操作,就使用$nexttick。
vue里实现nexttick的原理:(micro-task)promise -> MutationObserver ->(macro-task) setTimeout
2. setTimeout
是宏任务
setTimeout()是异步的宏任务。异步任务中先执行微任务后执行宏任务。
3. promise
是微任务
promise 在实例化的过程中所执行的代码都是同步进行的(new Promise),但是.then里面注册的回调函数是异步执行的,是异步任务中的微任务
注意 :
在同步代码执行完成后才会去检查是否有异步任务,并执行对应的回调,而微任务又会在宏任务之前执行
在当前的微任务没有执行完成时,是不会执行下一个宏任务的。