經常有小伙伴問到我什么是 js 的事件循環機制,這里我就簡單來給這些有困惑的小伙伴進行一下解答。
我將從下面幾個方面來循序漸進的為大家來進行講解:
區分進程和線程
js終止循環、在講解 js 事件循環機制之前,首先我們得說說進程與線程。兩者有什么區別呢?
這里做一個形象的比喻:
```js - 進程是一個工廠,工廠有它的獨立資源
下面我們再來完善一下這個概念:
js while循環,```js - 工廠的資源 -> 系統分配的內存(獨立的一塊內存)
怎么樣?這個比喻很貼切吧,接下來我們再到電腦中實際的看一下進程。
舉個例子,如果你是 windows 操作系統的電腦,你可以打開任務管理器,在里面可以看到一個后臺進程列表。
這里列表中的每一項,就是一個進程。如下圖:
js?所以,這下子你應該理解了,所謂進程,就是 cpu 資源分配的最小單位(系統會給它分配內存)
如果用較為官方的術語來描述的話,那就是:
注意: 1. 不同進程之間也可以通信,不過代價較大。 2. 現在,一般通用的叫法:單線程與多線程,都是指在一個進程內的單和多。所以核心還是得屬于一個進程才行。
瀏覽器是多進程的
到目前為止,你已經弄懂了進程與線程之間的區別。那么我們的瀏覽器在運行時也是會開啟一個進程么?
html for循環、打開 Google 瀏覽器,開啟多個標簽頁,然后打開任務管理器,如下圖:
可以看到,這里一個標簽頁就是一個進程。所以可以這么講:
注意:在這里瀏覽器應該也有自己的優化機制,有時候打開多個 tab 頁后,可以在 Chrome 任務管理器中看到,有些進程被合并了,所以每一個 Tab 標簽對應一個進程并不一定是絕對的。
瀏覽器包含哪些進程
上面已經說了,瀏覽器是多進程的,那么瀏覽器中具體包含哪些進程呢?
js循環事件?這里,我們主要來看一下瀏覽器渲染進程(也被稱之為瀏覽器內核)。
上面有提到,每當我們開啟一個新的 Tab 頁時,就新啟一個進程。而進程里面又有自己的多線程。大致有哪些線程呢?這里列舉一些主要常駐線程如下:
js 事件循環機制
在有了上面的知識進行鋪墊以后,我們總算可以來講解一下 js 的事件循環機制了。
我們知道,在 js 中任務會分為同步任務和異步任務。
如果是同步任務,則會在主線程(也就是 js 引擎線程)上進行執行,形成一個執行棧。
但是一旦遇到異步任務,則會將這些異步任務交給異步模塊去處理,然后主線程繼續執行后面的同步代碼。
注:異步模塊的處理功能,是由運行環境提供的,擁有和 js 引擎互不干擾的線程。
當異步任務有了運行結果以后,就會在任務隊列里面放置一個事件,這個任務隊列由事件觸發線程來進行管理。
一旦執行棧中所有的同步任務執行完畢,就代表著當前的主線程(js 引擎線程)空閑了,系統就會讀取任務隊列,將可以運行的異步任務添加到執行棧中,開始執行。
如下圖所示:
宏任務與微任務
在上文中,我們已經將 js 的事件循環機制梳理了一遍。
但是在上面的示意圖中,出現了宏任務與微任務的字樣,這究竟又是什么呢?
在 js 中,任務可以被分為 2 種類型:
宏任務(macrotask)與微任務(microtask)
宏任務可以理解為每次執行棧所執行的代碼就是一個宏任務,包括每次從事件隊列中獲取一個事件回調并放到執行棧中所執行的任務。
微任務可以理解為當前宏任務執行結束后立即執行的任務。
來看一個具體的例子:
```js console.log('script start');
setTimeout(function() { console.log('setTimeout'); }, 0);
Promise.resolve().then(function() { console.log('promise1'); }).then(function() { console.log('promise2'); });
console.log('script end'); ```
該代碼最終執行出來的結果為:
js script start script end promise1 promise2 setTimeout
原因很簡單,首先會執行同步的任務,輸出 script start 以及 script end,接下來由于 promise 是微任務,所以會在此次宏任務結束后立即輸出,而 setTimeout 由于是一個宏任務,所以會在上一次宏任務結束后,微任務結束后再執行。
來看一張下面的示意圖:
最后,我們來總結一下:
以上就是今天的分享啦~
如果大家有問題或者想了解更多的
技術干貨可以私信發送【微信】加朗妹兒微信喲~
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态