在寫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
當函數執行的時候,按照函數內部的順序依次執行,好比:若是此調用的函數是很耗時的,但它依然會等待調用函數的返回值,直到拿到預期的結果(即拿到了預期的返回值或者看到了預期的效果)爲止纔會執行後面的操做,那麼這個函數就是同步的。網絡
//在函數返回時,得到了預期值,即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事件循環機制