首先我們先看看同步與異步的定義,及瀏覽器的執行機制,方便我們更好地理解同步異步編程, 瀏覽器是多執行緒的,JS是單執行緒的(瀏覽器只分配一個執行緒來執行JS) 行程大執行緒小:一個行程中包含多個執行緒,例如在瀏覽器中打開一個HTML頁面就占用了一個行程,加載頁面的時候,瀏覽器分配一個執行緒去計算DOM樹,分配其它的執行緒去加載對應的資源檔案...再分配一個執行緒去自上而下執行JS
同步:在一個執行緒上(主堆疊/主任務佇列)同一個時間只能做一件事情,當前事情完成才能進行下一個事情(先把一個任務進堆疊執行,執行完成,在把下一個任務進堆疊,上一個任務出堆疊...)
異步:在主堆疊中執行一個任務,但是發現這個任務是一個異步的操作,我們會把它移除主堆疊,放到等待任務佇列中(此時瀏覽器會分配其它執行緒監聽異步任務是否到達指定的執行時間),如果主堆疊執行完成,監聽者會把到達時間的異步任務重新放到主堆疊中執行... [宏任務:macro task] - 定時器 - 事件系結 - ajax - 回呼函式 - Node中fs可以進行異步的I/O操作[微任務:micro task] - Promise(async/await) => Promise并不是完全的同步,當在Excutor中執行resolve或者reject的時候,此時是異步操作,會先執行then/catch等,當主堆疊完成后,才會再去呼叫resolve/reject把存放的方法執行 - process.nextTick (node中實作的api,把當前任務放到主堆疊最后執行,當主堆疊執行完,先執行nextTick,再到等待佇列中找)
- MutationObserver (創建并回傳一個新的 MutationObserver 它會在指定的DOM發生變化時被呼叫,)
執行順序優先級:SYNC => MICRO => MACRO
所有JS中的異步編程僅僅是根據某些機制來管控任務的執行順序,不存在同時執行兩個任務這一說法
先來看一個例子:
setTimeout(() => { console.log(1); }, 20); setTimeout(() => { console.log(2); }, 0);//=>默認會有最小的等待時間(V8一般是5~6MS) console.time('WHILE'); let i = 0; while (i <= 99999999) { i++; } console.timeEnd('WHILE'); setTimeout(() => { console.log(3); }, 10); console.log(4);
結果輸出如圖:


let xhr = new XMLHttpRequest(); xhr.open('GET', 'xxx.txt', false); // 放到等待區的時候,此時狀態是1 xhr.onreadystatechange = () => { console.log(xhr.readyState);//=>4 }; xhr.send();
// 同步ajax,xhr.send時為同步,xhr.send()執行完后狀態為4,任務狀態為4的時候主堆疊空閑,onreadystatechange監聽到狀態變化,輸出4
let xhr = new XMLHttpRequest(); xhr.open('GET', 'xxx.txt', false); xhr.send(); // 狀態已經為4了 xhr.onreadystatechange = () => {//=>狀態改變才會觸發,放到等待區的時候狀態已經為4了,不會在改變了,所以不會執行這個方法(啥都不會輸出) console.log(xhr.readyState); };
let xhr = new XMLHttpRequest(); xhr.open('GET', 'xxx.txt'); xhr.send();//=>異步操作:執行SEND后,有一個執行緒是去請求資料,主堆疊會空閑下來 // 放等待區之前狀態是1 xhr.onreadystatechange = () => { console.log(xhr.readyState);//=> 2 3 4 }; // 主堆疊又空閑了 // 狀態為2 把函式執行 // 狀態為3 把函式執行 // 狀態為4 把函式執行
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/165942.html
標籤:JavaScript
上一篇:js陣列物件過濾——filter,find,some,every
下一篇:js函式
