在寫js代碼的時候咱們每每都但願js代碼的執行順序是按照本身所想那樣執行,但結果總事與願違。因此今天就想花時間搞懂js的事件執行機制究竟是什麼樣的。javascript
js中事件分爲宏任務和微任務兩類,任務又分爲同步任務和異步任務。他們之間的執行順序將依次進行說明html
js中事件分爲兩類java
那麼等到何時才能執行呢?就是等到主線程的任務執行完畢爲空的時候。那咱們怎麼知道何時主線程爲空呢?js引擎存在monitoring process進程,會持續不斷的檢查主線程執行棧是否爲空,一旦爲空,就會去Event Queue那裏檢查是否有等待被調用的函數。 用流程圖來歸納上述步驟:node
let data = []; $.ajax({ url:www.javascript.com, data:data, success:() => { console.log('發送成功!'); } }) console.log('代碼執行結束'); 複製代碼
js中任務分爲兩類ajax
用流程圖表示上述流程:promise
setTimeout(function() { console.log('setTimeout'); },1000) new Promise(function(resolve) { console.log('promise'); }).then(function() { console.log('then'); }) console.log('console'); 複製代碼
如今看一個比較複雜的例子瀏覽器
console.log('1'); setTimeout(function() { console.log('2'); process.nextTick(function() { console.log('3'); }) new Promise(function(resolve) { console.log('4'); resolve(); }).then(function() { console.log('5') }) }) 輸出: 1 2 4 3 5 複製代碼
你們都知道js是是一門單線程語言,因此他的語句確定是一句一句執行的。可是js中又存在同步操做和異步操做,那麼就會有疑問,js是如何經過單線程的方式來實現異步操做的呢?bash
當函數執行的時候,按照函數內部的順序依次執行,好比:若是此調用的函數是很耗時的,但它依然會等待調用函數的返回值,直到拿到預期的結果(即拿到了預期的返回值或者看到了預期的效果)爲止纔會執行後面的操做,那麼這個函數就是同步的。markdown
//在函數返回時,得到了預期值,即2的平方根 Math.sqrt(2); //在函數返回時,得到了預期的效果,即在控制檯上打印了'hello' console.log('hello'); 複製代碼
若是函數是異步的,發出調用以後,立刻返回,可是不會立刻返回預期結果。調用者沒必要主動等待,當被調用者獲得結果以後會經過回調函數主動通知調用者。網絡
//讀取文件 fs.readFile('hello.txt', 'utf8', function(err, data) { console.log(data); }); //網絡請求 var xhr = new XMLHttpRequest(); xhr.onreadystatechange = xxx; // 添加回調函數 xhr.open('GET', url); xhr.send(); // 發起函數 複製代碼
上述示例中讀取文件函數 readFile和網絡請求的發起函數 send都將執行耗時操做,雖然函數會當即返回,可是不能馬上獲取預期的結果,由於耗時操做交給其餘線程執行,暫時獲取不到預期結果(後面介紹)。而在JavaScript中經過回調函數 function(err, data) { console.log(data); }和 onreadystatechange ,在耗時操做執行完成後把相應的結果信息傳遞給回調函數,通知執行JavaScript代碼的線程執行回調。
前面說到js是一門單線程語言,他是怎麼實現異步操做的呢。JS的運行一般是在瀏覽器中進行的,具體由JS引擎去解析和運行。下面咱們來具體瞭解一下瀏覽器。 瀏覽器的內核是多線程的。 一個瀏覽器一般由如下幾個常駐的線程:
須要注意的是,渲染線程和JS引擎線程是不能同時進行的。 渲染線程在執行任務的時候,JS引擎線程會被掛起。由於JS能夠操做DOM,若在渲染中JS處理了DOM,瀏覽器可能就不知所措了。
JS引擎能夠說是JS虛擬機,負責JS代碼的解析和執行。之因此說JavaScript是單線程,就是由於瀏覽器在運行時只開啓了一個JS引擎線程來解析和執行JS。那爲何只有一個引擎呢?若是同時有兩個線程去操做DOM,瀏覽器是否是又要不知所措了。 因此,雖然JavaScript是單線程的,但是瀏覽器內部不是單線程的。一些I/O操做、定時器的計時和事件監聽(click, keydown...)等都是由瀏覽器提供的其餘線程來完成的。也就是以前說的Event Queue。
JavaScript異步機制詳解
這一次,完全弄懂 JavaScript 執行機制
簡單總結下JS中EventLoop事件循環機制