20170610-async、await與Promise

async和await

  • async/await是一種編寫異步代碼的新方法,以前編寫異步代碼的方案是回調和promisehtml

  • async/await其實是創建在promise的基礎上,它不能與普通回調或者node回調一塊兒用node

  • async/await像promise同樣,也是非阻塞的promise

  • async/await讓異步代碼看起來、表現起來更像同步代碼,這正是其威力所在異步

語法(對比promise)

假設函數getJSON返回一個promise,而該promise的完成值是一個JSON對象,咱們只想調用它,並輸出該JSON,而後返回「done」async

  • promise的實現函數

const makeRequest = ()=>{
    getJSON().then(
        data => {
            console.log(data)
            return "done"
        }
    )
}

makeRequest()
  • async、await的實現調試

const makeRequest = async ()=>{
    console.log(await get.JSON())
    return "down"
}
makeRequest()
  • async、await與Promise的區別code

    • 函數前面有一個關鍵字 async。await 關鍵字只用在用 async 定義的函數內。全部 async 函數都會隱式返回一個 promise,而 promise 的完成值將是函數的返回值(本例中是 "done")。htm

    • 上面一點暗示咱們不能在代碼的頂層用 await,由於這樣就不是在 async 函數內。對象

    • await getJSON() 意味着 console.log 調用會一直等待,直到 getJSON() promise 完成並打印出它的值。

async/await的優點

簡潔乾淨

咱們沒必要寫 .then,建立一個匿名函數來處理響應,或者給不須要用的變量一個名稱 data。咱們還避免了代碼嵌套。這些小小的優點會快速累積起來,在後面的代碼中會變得更明顯。

錯誤處理

async/await 會最終讓咱們用一樣的結構( try/catch)處理同步和異步代碼變成可能。在下面使用 promise 的示例中,若是 JSON.parse 失敗的話,try/catch 就不會處理,由於它是發生在一個 prmoise 中。咱們須要在 promise 上調用 .catch,而且重複錯誤處理代碼。這種錯誤處理代碼會比可用於生產的代碼中的 console.log 更復雜。

const makeRequest = () => {  
  try {  
    getJSON().then(
      result => {  
        // 這裏發生錯誤
        const data = JSON.parse(result)  
        console.log(data)  
    }).catch((error)=>{
        console.log(error)
    })
  } catch (err) {  // 這裏不會捕捉到err
    console.log(err)  
  } 
}

如今看看用 async/await 實現的代碼。如今 catch 塊會處理解析錯誤。

const makeRequest = async () => { 
  try { // 這個解析會失敗   
    const data = JSON.parse(await getJSON()) 
    console.log(data) 
  } 
  catch (err) { 
    console.log(err)
  }
}

條件語句

假設想作像下面的代碼同樣的事情,獲取一些數據,並決定是否應該返回該數據,或者根據數據中的某些值獲取更多的細節。

const makeRequest = () => {  
  return getJSON()  
        .then(data => {  
            if (data.needsAnotherRequest) {  
                return makeAnotherRequest(data)  
                       .then(moreData => {  
                           console.log(moreData)  
                            return moreData  
                        })  
            } else {  
                console.log(data)  
                return data  
            }  
         })  
}

這些代碼看着就讓人頭疼。它只需將最終結果傳播到主 promise,卻很容易讓咱們迷失在嵌套( 6 層)、大括號和返回語句中。

把這個示例用async / await 重寫,就變得更易於閱讀。

const makeRequest = async () => {  
  const data = await getJSON()  
  if (data.needsAnotherRequest) {  
    const moreData = await makeAnotherRequest(data);  
    console.log(moreData)  
    return moreData  
  } else {  
    console.log(data)  
    return data  
  }  
}

中間值

你可能發現本身處於一種狀態,即調用你 promise1,而後用它的返回值來調用promise2,而後使用這兩個 promise 的結果來調用 promise3。你的代碼極可能看起來像這樣:

const makeRequest = () => {  
  return promise1()  
    .then(value1 => {  
        // do something  
          return promise2(value1)  
            .then(value2 => {  
            // do something  
                return promise3(value1, value2)  
        })  
      })  
 }

不過用 async/await 的話,一樣的邏輯就變得超級簡單直觀了。

const makeRequest = async () => {  
    const value1 = await promise1()  
    const value2 = await promise2(value1)  
    return promise3(value1, value2)  
}

調試

最後可是一樣重要的是,在使用 async/await 時,一個殺手級優點是調試更容易。調試 promise 一直是如此痛苦,有兩個緣由:

  • 無法在返回表達式(無函數體)的箭頭函數中設置斷點。

const makeRequest = () =>{
    return callAllPromise()
        .then(()=> callAllPromise())
        .then(()=> callAllPromise())
        .then(()=> callAllPromise())
        .then(()=> callAllPromise())
}
  • 若是在.then塊中設置斷點,並使用像單步調試這類調試快捷方式,調試器不會移動到後面的 .then ,由於它只單步調試同步代碼。

有了 async/await,咱們就再也不須要那麼多箭頭函數,您能夠像正常的同步調用同樣單步調試 await 調用。

const makeRequest = async ()=>{
    await callAllPromise()
    await callAllPromise()
    await callAllPromise()
    await callAllPromise()
}

引用資料

JavaScript 的 Async/Await 完勝 Promise 的六個理由
async 函數的含義和用法

相關文章
相關標籤/搜索