JS基礎——同步異步的區別

javascript語言是一門「單線程」的語言,
不像java語言,類繼承Thread再來個thread.start就能夠開闢一個線程。
因此,javascript就像一條流水線,僅僅是一條流水線而已,要麼加工,要麼包裝,不能同時進行多個任務和流程。javascript

「同步」——一下就讓人想到「一塊兒」這個詞;java


「異步」呢,從字面來說,好像是在不一樣的(異)的ways上do something,
那首先想到的詞多是「一邊...一邊...」,好比‘小明一邊吃雪糕一邊寫做業’,這徹底沒毛病,雪糕吃完了,做業也寫完了,這就是異步?那就大錯特錯了!ajax


其實同步和異步,
不管如何,作事情的時候都是隻有一條流水線(單線程)
同步和異步的差異就在於這條流水線上各個流程的執行順序不一樣。瀏覽器

最基礎的異步是setTimeout和setInterval函數,
很常見,可是不多人有人知道其實這就是異步,
由於它們能夠控制js的執行順序。咱們也能夠簡單地理解爲:
能夠改變程序正常執行順序的操做就能夠當作是異步操做。以下代碼:網絡

console.log( "1" );
    setTimeout(function() {
        console.log( "2" )
    }, 0 );
    setTimeout(function() {
        console.log( "3" )
    }, 0 );
    setTimeout(function() {
        console.log( "4" )
    }, 0 );
    console.log( "5" );

輸出順序是什麼呢?異步

clipboard.png

可見,儘管咱們設置了setTimeout(function,time)中的等待時間爲0,結果其中的function仍是後執行。async

儘管setTimeout的time延遲時間爲0,
其中的function也會被放入一個隊列中,等待下一個機會執行,
當前的代碼(指不須要加入隊列中的程序)必須在該隊列的程序完成以前完成,
所以結果可能不與預期結果相同。函數

這裏說到了一個「隊列」(即任務隊列),
該隊列放的是什麼呢,放的就是setTimeout中的function,
這些function依次加入該隊列,
即該隊列中全部function中的程序將會在該隊列之外的全部代碼執行完畢以後再以此執行,
這是爲何呢?由於在執行程序的時候,瀏覽器會默認setTimeout以及ajax請求這一類的方法都是耗時程序(儘管可能不耗時),
將其加入一個隊列中,該隊列是一個存儲耗時程序的隊列,在全部不耗時程序執行事後,再來依次執行該隊列中的程序。spa

又回到了最初的起點——javascript是單線程。 單線程就意味着,全部任務須要排隊,前一個任務結束,纔會執行後一個任務。
若是前一個任務耗時很長,後一個任務就不得不一直等着。

因而就有一個概念——任務隊列。若是排隊是由於計算量大,CPU忙不過來,倒也算了,
可是不少時候CPU是閒着的,由於IO設備(輸入輸出設備)很慢(好比Ajax操做從網絡讀取數據),不
得不等着結果出來,再往下執行。因而JavaScript語言的設計者意識到,這時主線程徹底能夠無論IO設備,
掛起處於等待中的任務,先運行排在後面的任務。等到IO設備返回告終果,再回過頭,把掛起的任務繼續執行下去。.net

因而,全部任務能夠分紅兩種,

一種是同步任務(synchronous),另外一種是異步任務(asynchronous)。 同步任務指的是,在主線程上排隊執行的任務,
只有前一個任務執行完畢,才能執行後一個任務; 異步任務指的是,不進入主線程、而進入"任務隊列"(task queue)的任務,
只有等主線程任務執行完畢,"任務隊列"開始通知主線程,請求執行任務,該任務纔會進入主線程執行。

具體來講,異步運行機制以下:


  1. 全部同步任務都在主線程上執行,造成一個執行棧(execution context stack)。
  2. 主線程以外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。
  3. 一旦"執行棧"中的全部同步任務執行完畢,系統就會讀取"任務隊列",看看裏面有哪些事件。那些對應的異步任務,因而結束等待狀態,進入執行棧,開始執行。
  4. 主線程不斷重複上面的第三步。

只要主線程空了,就會去讀取"任務隊列",這就是JavaScript的運行機制。這個過程會不斷重複。

"任務隊列"中的事件,除了IO設備的事件之外,
還包括一些用戶產生的事件(好比鼠標點擊、頁面滾動等等),
好比$(selectot).click(function),這些都是相對耗時的操做。
只要指定過這些事件的回調函數,這些事件發生時就會進入"任務隊列",等待主線程讀取。

所謂"回調函數"(callback),就是那些會被主線程掛起來的代碼,前面說的點擊事件$(selectot).click(function)中的function就是一個回調函數。異步任務必須指定回調函數,當主線程開始執行異步任務,就是執行對應的回調函數。例如ajax的success,complete,error也都指定了各自的回調函數,這些函數就會加入「任務隊列」中,等待執行。

做者:YinghaoGuo
來源:CSDN
原文:https://blog.csdn.net/qq_2285... 版權聲明:本文爲博主原創文章,轉載請附上博文連接!

相關文章
相關標籤/搜索