天天看點

JavaScript處理異步的幾種方法

回調(callback)是一個函數被作為一個參數傳遞到另一個函數裡,在那個函數執行完後再執行。

假定有兩個函數f1和f2,f2等待f1的執行結果,f1()–>f2();如果f1很耗時,可以改寫f1,把f2(箭頭函數)寫成f1的回調函數:

優點:簡單、友善、實用。

缺點:易形成回調函數地獄。如果我們隻有一個異步操作,用回調函數來處理是完全沒有任何問題的。。但是如果我們要嵌套很多個回調函數,問題就很大了,因為多個異步操作形成了強耦合,代碼将亂作一團,無法管理。這種情況被稱為"回調函數地獄"(callback hell)。

含義: Promise是異步程式設計的一種解決方案,

優點: Promise是鍊式程式設計,有效的解決了令人頭痛的回調地獄問題,Promise的結果有成功和失敗兩種狀态,隻有異步操作的結果,可以決定目前是哪一種狀态,外界的任何操作都無法改變這個狀态。

2.1 常用API

resolve 傳回異步操作成功的結果

reject 傳回異步操作失敗的結果

then 執行Promise狀态是成功的操作

catch 執行Promise狀态是失敗的操作

finally 不管Promise狀态是成功或失敗都執行的操作

2.2 Promise.all

Promise.all方法用于将多個 Promise 執行個體,包裝成一個新的 Promise 執行個體。

const p = Promise.all([p1, p2, p3])

p的狀态由p1、p2、p3決定,分成兩種情況。

(1)隻有p1、p2、p3的狀态都變成fulfilled,p的狀态才會變成fulfilled,此時p1、p2、p3的傳回值組成一個數組,傳遞給p的回調函數。

(2)隻要p1、p2、p3之中有一個被rejected,p的狀态就變成rejected,此時第一個被reject的執行個體的傳回值,會傳遞給p的回調函數。

采用事件驅動模式,任務的執行不取決代碼的順序,而取決于某一個事件是否發生。

監聽函數有:on,bind,listen,addEventListener,observe

舉例,為f1綁定一個事件(jquery寫法):f1.on(‘done’,f2);即當f1發生done事件,就執行f2。

優點:易了解,可綁定多個事件,每一個事件可指定多個回調函數,可以去耦合,有利于實作子產品化

缺點:整個程式都要變成事件驅動型,運作流程會變得不清晰

含義: Generator 函數是 ES6 提供的一種異步程式設計解決方案,文法行為與傳統函數完全不同。

基本用法:

特征:

function關鍵字與函數名之間有一個星号;

函數體内部使用yield表達式,定義不同的内部狀态;

通過next方法擷取每段狀态的傳回結果,上面分成4次執行了Gennrator函數。

第一次,擷取第一個yield函數的傳回結果并暫停,done:false,代表函數内的狀态還沒有執行結束;

第二次,同理;

第三次,擷取return 的傳回結果,done:true表示函數内的狀态已經執行完畢;

第四次,函數内已經沒有可以執行的狀态,所有傳回undfined,同時告訴函數内的狀态已經執行完畢;

如果函數内沒有return,在第三次時傳回undfined,done:true表示函數内的狀态已經執行完畢;

含義: async 函數是在ES2017 标準中引入的,async使得異步操作變得更加友善,其實他就是Generator 函數的文法糖

說明:

await指令隻能用在async函數之中,如果用在普通函數,就會報錯。

await後面是一個Promise對象,如get1 return出去的Promise執行個體;

如果不是 Promise 對象,就直接傳回對應的值,如直接傳回’111’。

若Promise 對象, 并且其以值 x 被 fulfilled, 則傳回值為 x.

Promise 對象, 并且其以異常 e 被 rejected, 則抛出異常 e

async函數傳回的 Promise 對象,必須等到内部所有await指令後面的 Promise 對象執行完,才會發生狀态 改變;

如果任何一個await語句後面的 Promise 對象變為reject狀态或遇到return,那麼整個async函數都會中斷執行。

await 在等待 Promise 對象時會導緻 async function 暫停執行, 一直到 Promise 對象決議之後才會 async function 繼續執行;

如果我們希望即使前一個異步操作失敗,也不要中斷後面的異步操作。這時可以将第一個await放在 try…catch結構裡面,這樣不管這個異步操作是否成功,第二個await都會執行。

優點: 相比Generator函數,async函數有如下四點改進

内置執行器: Generator 函數的執行必須靠next()進行每一次的子產品執行,async自帶執行器,隻需要和普通函數一樣調用即可執行

更好的語義:async表示函數裡有異步操作,await表示緊跟在後面的表達式需要等待結果。

傳回值是Promise: async函數的傳回值是 Promise 對象,可以用then方法指定下一步的操作;

而且async函數完全可以看做多個異步函數的操作,包裝成的一個 Promise 對象,而await指令就是内部then指令的文法糖,即Promise.all()的用法 ;

多個await指令後面的異步操作,如果不存在繼發關系,最好讓它們同時觸發。

參考文章(侵删)

繼續閱讀