JavaScript異步編程

目錄

  • JavaScript採用單線程模式工做的緣由
  • 單線程的優點和弊端
  • 同步模式與異步模式面試

    • 同步模式
    • 異步模式
    • 同步模式API和異步模式API的特色
  • 實現JavaScript異步編程的幾種方式編程

    • 回調函數 —— 全部異步編程方案的根基
    • Promise —— 更優的異步編程解決方案
    • Generator
    • async/await —— 異步操做的終極解決方案

JavaScript採用單線程模式工做的緣由

最先JavaScript語言就是運行在瀏覽器端的語言,目的是爲了實現頁面上的動態交互。實現頁面交互的核心就是DOM操做,這就決定了它必須使用單線程模型,不然就會出現很複雜的線程同步問題。segmentfault

假設在 js中有多個線程一塊兒工做,其中一個線程修改了這個 DOM元素,同時另外一個線程又刪除了這個元素,此時瀏覽器就沒法明確該以哪一個工做線程爲準。因此爲了不線程同步的問題,從一開始, js就設計成了單線程的工做模式。

因此,js是單線程工做模式,若是有多個任務,任務須要排隊,一個一個依次去執行。瀏覽器

單線程的優點和弊端

  • 優點:更安全,更簡單
  • 弊端:效率低,有些能夠同時執行的任務必須等待。若是中間有一個特別耗時的任務,其餘的任務就要等待很長的時間,會出現假死的狀況。

爲了解決這種問題,js有兩種任務的執行模式:安全

同步模式(Synchronous)異步模式(Asynchronous)異步

同步模式與異步模式

同步模式

指的是代碼的任務依次執行,後一個任務必須等待前一個任務結束才能開始執行。程序的執行順序和代碼的編寫順序是徹底一致的。在單線程模式下,大多數任務都會以同步模式執行。async

console.log('global begin')
function bar () {
    console.log('bar task') 
}
function foo () {
    console.log('foo task')
    bar()
}
foo()
console.log('global end')

// global begin
// foo task
// bar task
//global end

// 使用調用棧的邏輯

爲了不耗時函數讓頁面卡頓和假死,因此還有異步模式。異步編程

異步模式

該模式不會去等待這個任務的結束纔開始下一個任務,都是開啓事後就當即日後執行下一個任務,此時異步線程會單獨執行異步任務,耗時函數的後續邏輯會經過回調函數的方式定義,執行事後會將回調放到消息隊列中,js主線程執行完任務事後會依次執行消息隊列中的任務。這裏要強調,js是單線程的,瀏覽器不是單線程的,有一些API是有單獨的線程去作的。函數

下面看一個簡單的異步模式的例子:線程

console.log('global begin')
// 延時器
setTimeout(function timer1 () {
    console.log('timer1 invoke')
}, 1800)
// 延時器中又嵌套了一個延時器
setTimeout(function timer2 () {
    console.log('timer2 invoke')
    setTimeout(function inner () {
        console.log('inner invoke')
    }, 1000)
}, 1000)
console.log('global end')

// global begin
// global end
// timer2 invoke
// timer1 invoke
// inner invoke

//除了調用棧,還用到了消息隊列和事件循環

異步模式對於JavaScript語言很是重要,沒有它就沒法同時處理大量的耗時任務。對於開發者而言。單線程下面的異步最大的難點就是代碼執行的順序混亂 ,因此面試題裏面百分百會考這裏的內容 - -|||

同步模式API和異步模式API的特色

同步模式的API的特色:任務執行完代碼纔會繼續往下走,例如:console.log

異步模式的API的特色:下達這個任務開啓的指令以後代碼就會繼續執行,代碼不會等待任務的結束

實現JavaScript異步編程的幾種方式

回調函數 —— 全部異步編程方案的根基

回調函數:由調用者定義,交給執行者執行的函數

// callback就是回調函數
// 就是把函數做爲參數傳遞,缺點是不利於閱讀,執行順序混亂。
function foo(callback) {
    setTimeout(function(){
        callback()
    }, 3000)
}

foo(function() {
    console.log('這就是一個回調函數')
    console.log('調用者定義這個函數,執行者執行這個函數')
    console.log('其實就是調用者告訴執行者異步任務結束後應該作什麼')
})

還有其餘的一些實現異步的方式,例如:事件機制和發佈訂閱。這些也都是基於回調函數之上的變體。

Promise —— 更優的異步編程解決方案

主要爲了解決回調地獄問題,詳細瞭解參考 Promise(更優的異步編程解決方案)

Generator

詳細瞭解參考 Generator -> Generator異步方案

async/await —— 異步操做的終極解決方案

詳細瞭解參考 async&await -> async/await處理多回調異步

相關文章
相關標籤/搜索