async/await 並行請求和錯誤處理

async 順序

併發請求

使用async的時候,代碼執行的順序很容易出錯,好比咱們要同時發起兩個請求,可能會寫出下面的代碼javascript

function fetchName () {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('lujs')
    }, 3000)
  })
}

function fetchAvatar () {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('https://avatars3.githubusercontent.com/u/16317354?s=88&v=4')
    }, 4000)
  })
}

async fetchUser () {
  const name = await fetchName()
  const avatar = await fetchAvatar()
  return {
    name,
    avatar
  }
}

(async function () {
  console.time('should be 7s ')
  const user = await fetchUser()
  console.log(user)
  console.timeEnd('should be 3s ')
})()

在上面的代碼中,咱們認爲fetchName,fetchAvatar會並行執行,實際上並不會。fetchAvatar會等待fetchName執行完以後纔開始請求。fetchUser函數的執行時間不是三秒而是7秒 java

要並行請求的話須要像下面這樣寫,fetchUserParallel的執行時間爲4秒git

async function fetchUserParallel () {
  const namePromise = fetchName()
  const avatarPromise = fetchAvatar()
  return {
    name: await namePromise,
    avatar: await avatarPromise 
  }
}
(async function () {
  console.time('should be 3s, but time is ')
  const user = await fetchUser()
  console.log(user)
  console.timeEnd('should be 3s, but time is ')

  console.time('should be 3s : ')
  const user2 = await fetchUserParallel()
  console.log(user2)
  console.timeEnd('should be 3s : ')
})()

使用Promise.all來併發請求

function fetchList (id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`id is : ${id}`)
    }, 5000)
  })
}

async function getList () {
  const ary = [1, 2, 3, 4]
  const list =  Promise.all(
    ary.map(
      (id) => fetchList(id)))
  return await list
}
(async function () {
  // 使用promise併發請求
  console.time('should be 3s ')
  const list = await getList()
  console.log(list)
  console.timeEnd('should be 3s ')
})()

錯誤獲取

使用try...catch

try {
    const user3 = await fetchUser(true)
  } catch (err) {
    console.error('user3 error:', err)
  }

包裝promise,使其返回統一的格式的代碼

參考文章github

/**
   * 包裝promise, 使其返回統一的錯誤格式
   * @param {Promise} promise 
   */
  function to (promise) {
    return promise.then(res => [null, res]).catch(err => [err])
  }
  .
  .
  .
  const [err, res] = await to(fetchUser(true))
  if (err) {
    console.error('touser err:', err)
  }

繼續使用catch

// 由於async 返回的promise對象,因此可使用catch
  const user4 = await fetchUser(true).catch(err => {
    console.error('user4 error:', err)
  })
有興趣的能夠用弄得運行一下代碼,
在線例子
測試代碼
相關文章
相關標籤/搜索