JS面試題之異步


什么是異步

同步(sync)是一件事一件事的執行,只有前一個任務執行完畢才能執行后一個任務。異步(async)相對於同步,程序無須按照代碼順序自上而下的執行。

為什么要使用異步

由於js是單線程的,只能在js引擎的主線程上運行,所以js代碼只能一行一行的執行,如果沒有異步的存在,由於當前的任務還沒有完成,其他的所有操作都會無響應,用戶就會長時間的在等待。

JS常見的異步模式

常見的異步模式有六種:

  • 回調函數
  • 事件監聽
  • 發布/訂閱模式
  • promise
  • Generator(ES6)
  • async/await(ES7)

回調函數

回調函數是異步操作最基本的方法。

回調函數作為參數傳遞給另一個函數,在另一個函數中被調用。常見的回調函數的例子:

ajax(url, () => {
    //處理邏輯
})

但是使用回調函數,經常會寫出回調地獄,這是非常致命的。

回調地獄的根本問題是:

  • 嵌套函數存在耦合性
  • 嵌套函數變多,處理問題的困難也變大

事件監聽

事件監聽模式,異步任務的執行取決於,某個事件的發生。比如點擊事件(onClick)和內容改變時間(onChange)等。

發布/訂閱模式

在發布/訂閱模式中,想象有一個類似消息中心的地方,可以在消息中心“注冊”一條消息,然后就會有若干對這消息感興趣的人“訂閱”,一旦該消息被“發布”,所有”訂閱“了該消息的用戶都會得到提醒。

Promise

Promise是ES6推出的一種解決異步編程的解決方案。Promise是承諾的意思,這個承諾在未來會有一個確定的答復,該承諾有三種狀態:等待中(pending)、完成了(resolved)、拒絕了(rejected)。一旦狀態從等待改變為其他狀態就不再可變了。

Promise是個構造函數,接受一個函數作為參數。作為參數的函數有兩個參數:resolve和reject,分別對應完成和拒絕兩種狀態。我們可以選擇在不同時候執行resolve或reject去觸發下一個動作,執行then方法里的函數。

ajax(rul)
  .then(res => {
    console.log(res)
    return ajax(url1)
  }).then(res => {
    console.log(res)
    return ajax(url2)
  }).then(res => console.log(res))

Promise實現了鏈式調用,每次調用then之后返回的都是一個Promise對象,如果在then使用了return,return返回的值會被Promise.resolve()包裝。

Generator

Generator是一種特殊的函數,有以下特點:

  • 聲明時需要在function后面加上*,並且配合函數里面yield關鍵字使用。
  • 在執行Generator函數的時候,會返回一個Iterator遍歷器對象,通過其next方法,將Generator內的代碼以yield為分界分步執行。
  • 執行Generator函數時,代碼不會執行,而是需要調用Iterator遍歷器對象的next方法,這時程序才會執行從頭或從上一個yield到下一個yield或return或函數體尾部之間的代碼,並將yield后面的值包裝成json對象返回。
  • value取的yield或return后面的值,否則就是undefined,done的值如果碰到return或者執行完函數體會返回true,否則就會返回false。

Async/Await

一個函數如果加上async,那么該函數就會返回一個Promise對象。

async function test() {
    console.log('1')
}
console.log(test)	// Promise {<resolve>: "1"}

async就是將函數返回使用Promise.resolve(),和then處理返回值一樣,await只能配套async使用。但如果多個異步代碼沒有依賴性卻使用了await會導致性能降低。

async在使用上會有一些需要注意的地方:

  • async函數的返回值是一個Promise對象,不像是generator函數返回的是Iterator遍歷器對象,所以async函數執行后可以繼續使用then等方法來繼續執行后面的邏輯。
  • await后邊一般跟Promise對象,async函數執行遇到await后,等待后面的Promise對象的狀態從pending變成resolve后,將resolve的參數返回並自動往下執行知道下一個await或結束。
  • await后面也可以跟一個async進行嵌套使用。
    個人微信公眾號


免責聲明!

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



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