【譯】JavaScript中的async/await

異步的JavaScript從未如何簡單!過去段時間,咱們使用回調。而後,咱們使用promises。如今,咱們有了異步功能函數。javascript

異步函數可以使得(咱們)編寫異步JavaScript更加容易,可是,它自帶一套陷阱,對初學者很不友好。java

在這個由兩部分組成的文章中,我想分享下你須要瞭解的有關異步函數的內容。【PS:另外一部分暫不打算翻譯】git

異步功能

異步功能函數包含async關鍵詞。你能夠在正常的函數聲明中使用它:github

async function functionName (arguments) {
  // Do something asynchronous
}
複製代碼

你也能夠使用箭頭函數。數組

const functionName = async (arguments) => {
  // Do something asynchronous
}
複製代碼

異步函數老是返回promises

(異步函數)它無論你返回什麼。其返回值都是promisepromise

const getOne = async _ => { 
  return 1 
} 

const promise = getOne()
console.log(promise) // Promise 
複製代碼

筆記:在接着往前讀以前,你應該知道什麼是JavaScript Promises知識點,以及如何使用它們。不然,它會開始變得混亂。這篇文章會幫助你熟悉JavaScript Promise。異步

await關鍵字

當你調用promise時,你會在then中處理下一步,以下:async

const getOne = async _ => { 
  return 1 
} 

getOne()
  .then(value => {
    console.log(value) // 1
  })
複製代碼

await關鍵字容許你等待promise去解析。一旦解析完promise,它就會返回參數傳遞給then調用。函數

const test = async _ => {
  const one = await getOne()
  console.log(one) // 1
}

test()
複製代碼

返回await

在返回承諾(promise)以前沒有必要等待(await)。你能夠直接退回承諾。post

若是你return await些內容,則你首先是解決了原先promise。而後,你從已經解析的內容(resolved value)建立新的promise。return await真的沒作什麼有效的東西。無需額外的步驟。

// Don't need to do this 
const test = async _ => {
  return await getOne()
}

test()
  .then(value => {
    console.log(value) // 1
  })
複製代碼
// Do this instead
const test = async _ => {
  return getOne()
}

test()
  .then(value => {
    console.log(value) // 1
  })
複製代碼

注意:若是你不須要await,則不須要使用異步功能(async function)。上面的例子能夠改寫以下:

// Do this instead
const test = _ => {
  return getOne()
}

test()
  .then(value => {
    console.log(value) // 1
  })
複製代碼

處理錯誤

若是一個promise出錯了,你能夠使用catch調用來處理它,以下所示:

const getOne = async (success = true) => { 
  if (success) return 1
  throw new Error('Failure!')
} 

getOne(false)
  .catch(error => console.log(error)) // Failure!
複製代碼

若是你想在一個異步函數中處理錯誤,你須要調用try/catch

const test = async _ => {
  try {
    const one = await getOne(false)
  } catch (error) {
    console.log(error) // Failure!
  }
}

test()
複製代碼

若是你有多個await關鍵字,錯誤處理可能變得很難看...

const test = async _ => {
  try {
    const one = await getOne(false)
  } catch (error) {
    console.log(error) // Failure!
  }

  try {
    const two = await getTwo(false)
  } catch (error) {
    console.log(error) // Failure!
  }

  try {
    const three = await getThree(false)
  } catch (error) {
    console.log(error) // Failure!
  }
}

test()
複製代碼

還有更好的方法。

咱們知道異步函數老是返回一個promise。當咱們調用promise時,咱們能夠在catch調用中處理錯誤。這意味着咱們能夠經過添加.catch來處理異步函數中的任何錯誤。

const test = async _ => {
  const one = await getOne(false)
  const two = await getTwo(false)
  const three = await getThree(false)
}

test()
  .catch(error => console.log(error)))
複製代碼

注意:Promise的catch方法只容許你捕獲一個錯誤。

多個awaits

await阻止JavaScript執行下一行代碼,直到promise解析爲止。這可能會致使代碼執行速度減慢的意外效果。

爲了實際演示這點,咱們須要在解析promise以前建立一個延遲。咱們能夠使用sleep功能來建立延遲。

const sleep = ms => {
  return new Promise(resolve => setTimeout(resolve, ms))
}
複製代碼

ms是解析前等待的毫秒數。若是你傳入1000sleep函數,JavaScript將等待一秒才能解析promise。

// Using Sleep
console.log('Now')
sleep(1000)
  .then(v => { 
    console.log('After one second') 
  })
複製代碼

sleep

假設getOne須要一秒來解析。爲了建立這個延遲,咱們將1000(一秒)傳入到sleep。一秒事後,sleeppromise解析後,咱們返回值1。

const getOne = _ => {
  return sleep(1000).then(v => 1)
}
複製代碼

若是你使用await getOne(),你會發如今getOne解析以前須要一秒鐘。

const test = async _ => {
  console.log('Now')

  const one = await getOne()
  console.log(one)
}

test()
複製代碼

block-1

如今,假設你須要處理三個promises。每一個promise都有一秒鐘的延遲。

const getOne = _ => {
  return sleep(1000).then(v => 1)
}

const getTwo = _ => {
  return sleep(1000).then(v => 2)
}

const getThree = _ => {
  return sleep(1000).then(v => 3)
}
複製代碼

若是你連續await這三個promises,你將要等待三秒才能解析完全部promises。這並很差,由於咱們強迫JavaScript在作咱們須要作的事情以前等待了兩秒鐘。

const test = async _ => {
  const one = await getOne()
  console.log(one)

  const two = await getTwo()
  console.log(two)

  const three = await getThree()
  console.log(three)

  console.log('Done')
}

test()
複製代碼

block-2

若是getOnegetTwogetThree能夠同時獲取,你將節省兩秒鐘。你能夠使用Promise.all同時獲取這三個promises。

有三個步驟:

  1. 建立三個promises
  2. 將三個promises添加到一個數組中
  3. 使用Promise.allawaitpromises數組

以下所示:

const test = async _ => {
  const promises = [getOne(), getTwo(), getThree()]
  console.log('Now')

  const [one, two, three] = await Promise.all(promises)
  console.log(one)
  console.log(two)
  console.log(three)

  console.log('Done')
}

test()
複製代碼

block-3

這就是你須要瞭解的基本異步功能函數!我但願這篇文章爲你掃除了些障礙。

筆記:這篇文章是Learn JavaScript的修改摘錄。若是你發現本文有用,你可能須要去查看它。

後話

原文:zellwk.com/blog/async-…

文章首發:github.com/reng99/blog…

至此,系列文callbacks,promisesasync/await共三篇文章已經完成~

更多內容:github.com/reng99/blog…

相關文章
相關標籤/搜索