macrotask和microtask以及EventLoop的介绍
前言
提起js,有這么幾個(gè)概念非了解不可。單線(xiàn)程 、回調(diào)函數(shù)、非阻塞、執(zhí)行上下文、調(diào)用棧、上下文、事件循環(huán)、任務(wù)隊(duì)列。
單線(xiàn)程
one thread = one call stack == one thing at a time 解釋來(lái)講就是單線(xiàn)程意味著只有一個(gè)調(diào)用棧,在同一時(shí)刻只能做一件事兒
執(zhí)行上下文
執(zhí)行上下文就是當(dāng)前JavaScript代碼被解析和執(zhí)行是所在環(huán)境的抽象概念,JavaScript中運(yùn)行任何的代碼都是在執(zhí)行上下文中運(yùn)行。
執(zhí)行上下文的類(lèi)型,總共有三類(lèi) 1.全局執(zhí)行上下文:這是默認(rèn)的,最基礎(chǔ)的執(zhí)行上下文。不在任何函數(shù)中的代碼都位于全局執(zhí)行上下文中。共有兩個(gè)過(guò)程: - .創(chuàng)建有全局對(duì)象,在瀏覽器中這個(gè)全局對(duì)象就是window對(duì)象。 - .將this指針指向這個(gè)全局對(duì)象。一個(gè)程序中只能存在一個(gè)執(zhí)行上下文。 2.函數(shù)執(zhí)行上下文:每次調(diào)用函數(shù)時(shí),都會(huì)為該函數(shù)創(chuàng)建一個(gè)新的執(zhí)行上下文。每個(gè)函數(shù)都擁有自己的執(zhí)行上下文,但是只有在函數(shù)被調(diào)用的時(shí)候才會(huì)被創(chuàng)建。一個(gè)程序中可以存在多個(gè)函數(shù)執(zhí)行上下文。 3.Eval函數(shù)執(zhí)行上下文:運(yùn)行在eval函數(shù)中的代碼也獲得了自己的執(zhí)行上下文(不建議使用)
(執(zhí)行棧)調(diào)用棧
執(zhí)行棧,也叫調(diào)用棧,用于存儲(chǔ)在代碼執(zhí)行期間創(chuàng)建的所有執(zhí)行上下文。 當(dāng)JavaScript引擎首次讀取腳本時(shí),會(huì)創(chuàng)建一個(gè)全局執(zhí)行上下文并將其Push到當(dāng)前執(zhí)行棧中。每當(dāng)發(fā)生函數(shù)調(diào)用時(shí),引擎都會(huì)為該函數(shù)創(chuàng)建一個(gè)新的執(zhí)行上下文并Push到當(dāng)前執(zhí)行棧的棧頂
任務(wù)隊(duì)列、macrotask、mircotask
同步任務(wù)和異步任務(wù)
因 js是單線(xiàn)程語(yǔ)言 , 存在大量的IO等耗時(shí)操作,所以有“同步任務(wù)”和“異步任務(wù)”的區(qū)分 同步任務(wù)
在主線(xiàn)程上排隊(duì)執(zhí)行的任務(wù),前一個(gè)任務(wù)執(zhí)行完畢,才能執(zhí)行后一個(gè)任務(wù); 異步任務(wù) 不進(jìn)入主線(xiàn)程、而進(jìn)入”任務(wù)隊(duì)列”(task queue)的任務(wù),只有”任務(wù)隊(duì)列”通知主線(xiàn)程,某個(gè)異步任務(wù)可以執(zhí)行了,該任務(wù)才會(huì)進(jìn)入主線(xiàn)程執(zhí)行。 總之 只要主線(xiàn)程空了,就會(huì)去讀取”任務(wù)隊(duì)列”,這就是JavaScript的運(yùn)行機(jī)制,這個(gè)過(guò)程是循環(huán)往復(fù)的,所以也叫做Event Loop事件循環(huán)
macrotask、mircotask隊(duì)列
microtasks:
- process.nextTick
- promise
- Object.observe
- MutationObserver
macrotasks:
- setTimeout
- setInterval
- setImmediate
- I/O
- UI渲染
一個(gè)事件循環(huán)有一個(gè)或多個(gè)任務(wù)隊(duì)列,一個(gè)任務(wù)隊(duì)列是任務(wù)的集合 whatwg規(guī)范:html.spec.whatwg.org/multipage/w…
- task queue 就是 macrotask queue
- 每一個(gè) event loop 都有一個(gè) microtask queue
- task queue == macrotask queue != microtask queue
- 一個(gè)任務(wù) task 可以放入 macrotask queue 也可以放入 microtask queue 中
理解了這些定義之后,再看執(zhí)行原理:
事件循環(huán)的順序,決定了JavaScript代碼的執(zhí)行順序。它從script(整體代碼)開(kāi)始第一次循環(huán)。之后全局上下文進(jìn)入函數(shù)調(diào)用棧。直到調(diào)用棧清空(只剩全局),然后執(zhí)行所有的micro-task。當(dāng)所有可執(zhí)行的micro-task執(zhí)行完畢之后。循環(huán)再次從macro-task開(kāi)始,找到其中一個(gè)任務(wù)隊(duì)列執(zhí)行完畢,然后再執(zhí)行所有的micro-task,這樣一直循環(huán)下去。
更為形象的顯示代碼的執(zhí)行過(guò)程,請(qǐng)看https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
還要注意一點(diǎn):
包裹在一個(gè) script 標(biāo)簽中的js代碼也是一個(gè) task 確切說(shuō)是 macrotask。
事件循環(huán)
執(zhí)行棧中執(zhí)行完之后會(huì)從任務(wù)隊(duì)列中讀取一個(gè)task進(jìn)行執(zhí)行,這個(gè)過(guò)程是循環(huán)的,稱(chēng)之為 "事件循環(huán)"
非阻塞
遇到異步操作,主線(xiàn)程會(huì)繼續(xù)處理后面的代碼,當(dāng)異步操作完成以后在任務(wù)隊(duì)列(task)中添加事件
引用了:blog.csdn.net/sjn0503/art…
轉(zhuǎn)載于:https://juejin.im/post/5d0788a9e51d45773e418a79
總結(jié)
以上是生活随笔為你收集整理的macrotask和microtask以及EventLoop的介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 全球最大的苹果硬件收藏之一将拍卖,含 5
- 下一篇: 口袋妖怪黑2白2中文版二周目超详细图文攻