js中的同步和異步


一、單線程

JavaScript 語言的一大特點就是單線程,也就是說,同一個時間只能做一件事,需要排隊執行。如果前面的A任務會花費大量的時間,就會導致后面的B任務停止執行,知道A執行完才會執行B。如果排隊是因為計算量大,CPU忙不過來,倒也算了,但是很多時候CPU是閑着的,因為IO設備(輸入輸出設備)很慢(比如Ajax操作從網絡讀取數據,進行大量計算),不得不等着結果出來,再往下執行。

console.log(Date.now());
console.log('===========');
console.log(Date.now());
for (let i = 0; i < 100000000; i++) {
}
console.log('=====');
console.log(Date.now());
        
        //輸出
        1644333664879
        ===========
        1644333664879
        =====
        1644333664922

 前兩個時間戳因為代碼執行很快輸出的時間戳相同,相隔一個for循環后,第三個時間戳輸出與前兩個相差較大相差43毫秒。

 

這個時候JavaScript語言的設計者意識到,這時主線程完全可以不管IO設備,掛起處於等待中的任務,先運行排在后面的任務。等到IO設備返回了結果,再回過頭,把掛起的任務繼續執行下去。

二、同步和異步

為了防止主線程的不阻塞,異步方案產生。 所有任務可以分成兩種,一種是同步任務(synchronous),另一種是異步任務(asynchronous)。同步任務指的是:在主線程上排隊執行的任務,只有前一個任務執行完畢,才能執行后一個任務;異步任務指的是:不進入主線程、而進入"任務隊列"(task queue)的任務,只有"任務隊列"通知主線程,某個異步任務可以執行了,該任務才會進入主線程執行。任務隊列其實是一個先進先出的數據結構

(1)所有同步任務都在主線程上執行,形成一個執行棧(execution context stack)。

(2)主線程之外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。

(3)一旦"執行棧"中的所有同步任務執行完畢,系統就會讀取"任務隊列",看看里面有哪些事件。那些對應的異步任務,於是結束等待狀態,進入執行棧,開始執行。

(4)主線程不斷重復上面的第三步。

console.log(Date.now());
console.log('===========');
console.log(Date.now());
setTimeout(() => {
for (let i = 0; i < 100000000; i++) {
            }
console.log('異步2s');
console.log(Date.now());
        }, 2000)
setTimeout(() => {
for (let i = 0; i < 100000000; i++) {
            }
console.log('異步1s');
console.log(Date.now());
        }, 1000)
console.log('=====');
console.log(Date.now());
     
 //輸出
1644334680961
===========
 1644334680961
 =====
 1644334680961
 異步1s
1644334682005
異步2s
1644334683012

用定時器(異步操作)將for循環包裹起來,使for循環成為異步操作,不進入主線程。進入隊列任務開始執行。使三個時間戳的輸出相近,不會因為for循環而等待大量時間。

異步1s輸出的時間戳和前一個同步時間戳相差1044毫秒(減去for循環的43毫秒可看作1000毫秒了),異步2s和異步1s相差1007毫秒。

意味着異步任務一進入隊列任務就開始執行,執行完成后會在任務隊列放置一個結果的事件。當同步認證執行完成后,會進入任務隊列讀取已經執行完成的異步任務的回調函數結果並輸出。

單線程從從任務隊列中讀取任務是不斷循環的,每次棧被清空后,都會在任務隊列中讀取新的任務,如果沒有任務,就會等到,直到有新的任務,這就叫做任務循環,因為每個任務都是由一個事件觸發的,因此也叫作事件循環

三、異步回調函數的理解

普通函數是從上到下執行的,而異步函數你是不知道他在什么時候會執行完,但是你有想在他執行完的時候處理結果怎么辦?使用回調函數,異步任務的回調函數會在這個異步任務執行完的時候進行調用,進行處理異步任務的數據。

所以說普遍的異步任務都會有一個回調函數,進行數據的處理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM