javascript 運行時
- 堆記錄了內(nèi)存的分配
- 調(diào)用棧是棧幀這類東西所在的地方
setTimeout或者DOM黔漂,HTTP請求這些東西并不存在于V8引擎中
那我們?nèi)绾芜M行異步編程呢乡数?
- 上圖中包含了V8運行環(huán)境
- 然后是瀏覽器提供的其它部分WebAPIs(DOM,AJAX,setTimeout)
- 再然后就是事件循環(huán)event loop 和 回調(diào)隊列 call back queue
單線程
- javascript是一個單線程的編程語言
- 單線程的運行環(huán)境姐浮,它有且只有一個調(diào)用棧诡延,它每次只能夠做一件事情
call stack 調(diào)用棧
什么是調(diào)用棧
記錄當(dāng)前程序所在位置的數(shù)據(jù)結(jié)構(gòu)
- 如果當(dāng)前進入了某個函數(shù)慕的,v8就創(chuàng)建一個棧幀壓入棧中
- 如果當(dāng)前離開了某個函數(shù)叠殷,該棧幀就會被彈出棧外
你可以借助如下動圖理解call stack
當(dāng)我們在Chrome的控制臺上運行如下代碼時,會拋出一個異常揖庄,它將整個棧樹都打印了出來
錯誤是從foo開始栗菜,到bar,到baz,再到匿名函數(shù),也就是上圖中的main函數(shù)
內(nèi)存泄露
如果我們有一個調(diào)用自身的函數(shù)foo,那么會發(fā)生什么呢蹄梢?
阻塞
沒有什么嚴(yán)格意義上的阻塞疙筹,阻塞僅僅指的是代碼運行很慢,比如說
- console.log不慢,但是遍歷從1到10億很慢
- http請求很慢
- 加載圖片很慢
反正在調(diào)用棧里表現(xiàn)很慢的東西都叫阻塞
同步任務(wù)和異步任務(wù)
javascript程序中任務(wù)可以分為兩類
- 1 同步任務(wù)
- 2 異步任務(wù)
同步任務(wù)會依次進入call stack調(diào)用棧中執(zhí)行
異步任務(wù)會被v8引擎放入 任務(wù)隊列中而咆,只有當(dāng)同步任務(wù)全部執(zhí)行完畢霍比,異步任務(wù)才會從隊列首部至尾部依次進入調(diào)用棧執(zhí)行
任務(wù)隊列和事件循環(huán)
V8引擎提供了兩個東西
- 1一個正在運行的主線程
- 2 task queue 任務(wù)隊列(用于存放程序中的異步任務(wù))
- 每一個異步任務(wù)都有一個為了處理這個異步任務(wù)相關(guān)聯(lián)的函數(shù)
- 1 主線程會去執(zhí)行所有的同步任務(wù)。
- 2 等到同步任務(wù)全部執(zhí)行完翘盖,就會去看任務(wù)隊列里面的異步任務(wù)桂塞。
- 3 如果滿足條件凹蜂,那么異步任務(wù)就重新進入主線程開始執(zhí)行馍驯,這時它就變成同步任務(wù)了。
- 4 等到執(zhí)行完玛痊,下一個異步任務(wù)再進入主線程開始執(zhí)行汰瘫。一旦任務(wù)隊列清空,程序就結(jié)束執(zhí)行
通過下面動圖加深理解
事件循環(huán)
異步任務(wù)的寫法通常是回調(diào)函數(shù)s擂煞。一旦異步任務(wù)重新進入主線程混弥,就會執(zhí)行對應(yīng)的回調(diào)函數(shù)。如果一個異步任務(wù)沒有回調(diào)函數(shù)对省,就不會進入任務(wù)隊列蝗拿,也就是說,不會重新進入主線程蒿涎,因為沒有用回調(diào)函數(shù)指定下一步的操作哀托。
javaScript 引擎怎么知道異步任務(wù)有沒有結(jié)果,能不能進入主線程呢劳秋?答案就是引擎在不停地檢查仓手,一遍又一遍,只要同步任務(wù)執(zhí)行完了玻淑,引擎就會去檢查那些掛起來的異步任務(wù)嗽冒,是不是可以進入主線程了。這種循環(huán)檢查的機制补履,就叫做事件循環(huán)(Event Loop)
總結(jié)
V8引擎主要做了哪些事情
1 將異步任務(wù)掛起添坊,
2 主線程依次執(zhí)行同步任務(wù)
3 執(zhí)行同步任務(wù)的同時,事件循環(huán)(event loop)定時查看異步任務(wù)的結(jié)果箫锤,符合條件的異步任務(wù)放入到任務(wù)隊列中
4 程序中所有同步任務(wù)執(zhí)行完畢后贬蛙,主線程按照隊列先進先出的特點,總是從最先進入隊列的一個任務(wù)開始處理
5 每一個任務(wù)都有一個與之相關(guān)的處理函數(shù)麻汰,只有當(dāng)這個函數(shù)完全執(zhí)行完后速客,才能處理下一個任務(wù)
6 當(dāng)所有異步任務(wù)執(zhí)行完畢之后,程序結(jié)束