JS 主线程不断的循环往复的从任务队列中读取任务,执行任务,这种运行机制称为事件循环(event loop)推荐看一个2分钟了解event loop
宏任务和微任务
浏览器的事件循环(event loop)中分成宏任务和微任务。JS 中任务分成同步任务和异步任务。
- 宏任务(macro task)
JS 中主栈执行的大多数的任务,例如:定时器,事件绑定,ajax,回调函数,node中fs操作模块等就是宏任务
- 微任务(micro task)
promise, async/await, process.nextTick等就是微任务。
为什么要引入微任务,只有宏任务可以吗?
微任务的引入是为了解决异步回调的问题,假设只有宏任务,那么每一个宏任务执行完后回调函数也放入宏任务队列,这样会造成队列多长,回调的时间变长,这样会造成页面的卡顿,所以引入了微任务。
- 宏任务和微任务的执行顺序(很重要)
- 主栈队列就是一个宏任务,每一个宏任务执行完就会执行宏任务中的微任务,直到微任务全部都执行完,才开始执行下一个宏任务。
- js 中任务的执行顺序优先级是:主栈全局任务(宏任务) > 宏任务中的微任务 > 下一个宏任务。,所以 promise(微任务) 的执行顺序优先级高于setTimeout定时器。
- 不能满目的将 .then 的回调放入微任务队列;因为没有调用 resolve或者reject 之前是不算异步任务完成的, 所以不能将回调随意的放入微任务事件队列
- await 是一个让出线程的标志。await 后面的表达式会先执行一遍,将 await 后面的代码加入到 micro task中这个微任务是 promise 队列中微任务,然后就会跳出整个 async 函数来继续执行后面的代码。
- process.nextTick 是一个独立于 eventLoop 的任务队列,主栈中的宏任务每一次结束后都是先执行 process.nextTick队列,在执行微任务 promise 的 .then()。
- 每一个宏任务和宏任务的微任务执行完后都会对页面 UI 进行渲染。