JavaScript異步編程幾種方式

前言

    JavaScript程序執行是單線程,既程序按順序一步一步向下執行,後面的程序必須等前面的程序執行完畢,這樣容易形成程序阻塞,浪費CPU資源,瀏覽器容易進入假死狀態(無響應),用戶體驗差,這時異步編程相應而出...ajax

一  回調函數(callback)

   回調函數是做爲函數參數形式來執行的, 它是最基礎的異步執行方法,讓咱們看一個例子,編程

定義三個函數,fun2利用setTimeout實現異步函數,執行結果分別是1,3,2數組


當咱們但願輸出1,2,3時,fun3輸出的順序依賴fun2時,咱們能夠把fun3做爲fun2的回掉函數promise


fun2(fun3)複製代碼

若後者等待前者的執行結果,採用這種方式,咱們把同步操做變成了異步操做,fun2便不會堵塞程序運行,至關於先執行程序的主要邏輯,將耗時的操做推遲執行。瀏覽器

二 Promise

在傳統的ajax請求中,當異步請求之間的數據存在依賴關係的時候,就可能產生多層的回調fun1(fun2(fun3(fun4(...)))),這樣會使代碼邏輯很容易形成混亂不便於閱讀和後期維護。另外一方面,每每錯誤處理的代碼和正常的業務代碼耦合在一塊兒,形成代碼會極其難看。爲了讓編程更美好,咱們就須要引入 promise來下降異步編程的複雜性。

它每個異步任務返回一個Promise對象,該對象有一個then方法,容許指定回調函數,即:bash

fun2.then(fun3)
fun2.then(fun3).then(fun4)//能夠指定多個回掉函數
fun2.then(fun3).fail(fun4)//指定發生錯誤時的回調函數複製代碼

ES6規定,Promise對象是一個構造函數,用來生成Promise實例。Promise構造函數接受一個函數做爲參數,該函數的兩個參數分別是resolvereject。它們是兩個函數,由JavaScript引擎提供,不用本身部署。異步

resolve函數負責把promise狀態從「未完成」到「完成」(Pending 到Resolved),且異步函數執行成功後把狀態做爲參數傳遞出去;reject函數把promise狀態從「未完成」到「失敗」async

Promise實例生成之後,能夠用then方法分別指定Resolved狀態和Reject狀態的回調函數。then方法接收兩個回掉函數做爲參數,一個是Promise對象爲Resolved狀態時調用,另外一個是爲Rejected(可選)狀態時調用。異步編程

promise.then(function(value) {
  // success
}, function(value) {
  // failure
});
複製代碼

Promise.prototype.then()

     then方法返回的是一個新的Promise實例(注意,不是原來那個Promise實例)。所以能夠採用鏈式寫法,即then方法後面再調用另外一個then方法。函數

Promise.prototype.catch()

   Promise.prototype.catch方法是.then(null, rejection)的別名,用於指定發生錯誤時的回調函數。

Promise.all()

   Promise.all方法用於將多個Promise實例,包裝成一個新的Promise實例。Promise.all方法接受一個數組做爲參數,每一個數組也是一個新到promise,當狀態都爲Resolve時,有一個爲rejected,返回的promise狀態就變成rejected

三 async/await

    async 會將其後的函數(函數表達式或 Lambda)的返回值封裝成一個 Promise 對象,而 await 會等待這個 Promise (也能夠是任意表達式)完成,並將其 resolve 的結果返回出來。

function fun1 () {  console.log('1')}
function fun2 () {  return new Promise((resolve, reject) => {    setTimeout(() => {      console.log('2')      resolve()    }, 500)  })}
function fun3 () {  console.log('3')}
async function asyncFun () {  fun1()  await fun2()  fun3()}asyncFun()複製代碼
相關文章
相關標籤/搜索