官术网_书友最值得收藏!

1.7 異步編程

1.7.1 ES5中的異步

JavaScript引擎是基于事件循環的概念實現的,JavaScript引擎會把任務放在一個任務隊列中,通過事件循環機制一一執行任務隊列里的任務,從第一個依次執行到最后一個。有些任務執行可能時間會比較長,如果等待時間比較長的任務執行完成之后再執行下一個任務就會影響用戶體驗,所以JavaScript在設計的時候就有了同步和異步。異步任務不進入主線程,而進入任務隊列中的任務,只有任務隊列通知主線程,某個異步任務可以執行了,這個任務才會進入主線程執行。異步任務在ES5標準中通過回調來解決執行順序問題,代碼如下:

上述代碼通過setTimeout模擬異步過程,想要異步邏輯執行完成之后再執行"執行完之后的回調打印...",可以通過回調的方式來實現,把function(){}作為cb參數傳入異步邏輯中,在異步邏輯執行完成之后再執行回調函數,這樣就可以實現執行之后執行打印邏輯。這種寫法可以通過回調來控制異步執行問題,但是如果回調過多就會出現“回調地獄”的情況。如下:

上述代碼回調過多,如果邏輯比較復雜,會導致后期再更新維護的時候變得復雜,所以針對這種情況,ES6標準中出現Promise來解決異步問題,可以將回調的寫法變得更加簡潔。

1.7.2 Promise基本語法

首先Promise是系統中預定義的類,通過實例化可以得到Promise對象。Promise對象會有三種狀態,分別是pending、resolved、rejected,代碼如下:

上述代碼中Promise回調函數里如果沒有調取resolve或者reject,那么就會返還一個Pending狀態的Promise對象。如果調取了resolve函數就會返還一個resolved狀態的Promise對象(在火狐上略有不同,會顯示fullfilled狀態的Promise對象)。如果調取了reject函數則會返還一個rejected狀態的對象。每一個Promise對象都會有一個then方法,then方法里會接收兩個參數(可選),代碼如下:

上述代碼中如果調用resolve函數,在執行then的時候會執行到第一個成功的回調中去,如果調取reject函數則會執行到then的第二個錯誤的回調中去。當然Promise也提供catch方法來捕捉reject錯誤,代碼如下:

使用catch的好處是如果有多個then,會把最先報錯的錯誤拋出到catch里面。這樣在寫法上更加簡單。調用then函數之后會有三種返還值。

1)then里沒有返還值,會默認返還一個Promise對象。

2)then里如果有返還值會將返還值包裝成一個Promise對象返還。

3)如果返還的是Promise對象,then函數也會直接返還原本的Promise對象。代碼如下:

1.7.3 Promise處理異步問題

了解Promise基本用法之后就可以通過Promise來處理異步問題了,在寫法上可以理解為,通過Promise里提供的resolve及reject替換原本處理異步的回調函數。這樣可以使用Promise對象提供的then方法,由于每個then方法又會返還一個Promise對象,所以就可以實現then的鏈式調用,從而解決回調地獄的問題。代碼如下:

涉及多個異步邏輯的時候就可以使用then的鏈式操作,代碼如下:

通過上述代碼可以看出通過Promise及then的返還特性將異步改寫成then的鏈式操作,這樣就避免了回調地獄的情況,寫法上也變得更加優雅。在ES7標準中新增了async及await使上述Promise變得更加簡單和易用,如果不考慮兼容性,或者有自動化工具的情況下,建議使用async和await寫法,讓代碼變得更易懂簡單,代碼如下:

上述代碼中通過async和await將Promise鏈式操作改寫成同步寫法,讓代碼在可讀性及可維護性上變得更加簡單。

1.7.4 Promise里的其他方法

在Promise類上提供靜態方法創建Promise對象,可以通過Promise.resolve來創建一個resolved狀態的Promise對象,也可以通過Promise.reject來創建一個rejected狀態的Promise對象。代碼如下:

同樣也可以通過Promise.all來執行多個Promise對象,代碼如下:

使用Promise.all()函數時需要注意,接收的參數是一個數組,當所有Promise對象都執行成功之后才會拿到執行結果的數組。Promise.race()方法則不同,會返還最先執行的結果,無論成功還是失敗。

上述代碼中,三個異步Promise對象中p2會執行得最快,所以then回調里得到的就是p2的執行結果。

主站蜘蛛池模板: 仙桃市| 略阳县| 汉源县| 奈曼旗| 鹤峰县| 桓台县| 明溪县| 咸宁市| 嘉义县| 光泽县| 阜阳市| 巨野县| 和政县| 广昌县| 义马市| 湛江市| 武功县| 家居| 开江县| 卢氏县| 广德县| 筠连县| 辽宁省| 青州市| 四子王旗| 东兰县| 灌南县| 兴文县| 饶河县| 信宜市| 奉化市| 全南县| 新丰县| 三河市| 鞍山市| 龙江县| 姚安县| 乌拉特前旗| 清徐县| 遂昌县| 保康县|