async/await 你是會用,但是你知道怎麼處理錯誤嗎?

Sunshine_Lin發表於2022-02-18

前言

大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎是進階的前提是我的初心

Promise封裝請求

大家平時如果使用 Promise 封裝請求,那麼當你使用這個請求函式的時候是這樣的:

// 封裝請求函式
const request = (url, params) => {
  return new Promise((resolve, reject) => {
    // ...do something
  })
}

// 使用時
const handleLogin = () => {
  request(
    '/basic/login',
    {
      usename: 'sunshine',
      password: '123456'
    }
  ).then(res => {
    // success do something
  }).catch(err => {
    // fail do something
  })
}

可以看到,當你的請求成功時,會呼叫 then 方法,當你的請求失敗時會呼叫 catch 方法。

async/await

Promise 的出現解決了很多問題,但是如果請求多了且有順序要求的話,難免又會出現 巢狀 的問題,可讀性較差,比如:

const handleLogin = () => {
  request(
    '/basic/login',
    {
      usename: 'sunshine',
      password: '123456'
    }
  ).then(res => {
    // 登入成功後獲取使用者資訊
    request(
      '/basic/getuserinfo',
      res.id
    ).then(info => {
      this.userInfo = info
    }).catch()
  }).catch(err => {
    // fail do something
  })

所以這個時候 async/await 出現了,他的作用是:用同步的方式執行非同步操作,上面的程式碼使用 async/await 的話可以改寫成:

const handleLogin = async () => {
  const res = await request('/basic/login', {
    usename: 'sunshine',
    password: '123456'
  })
  const info = await request('/basic/getuserinfo', {
    id: res.id
  })
  this.userInfo = info
}

這樣的話程式碼的可讀性比較高,而不會出現剛剛的巢狀問題,但是現在又有一個問題了,Promise有 catch 這個錯誤回撥來保證請求錯誤後該做什麼操作,但是 async/await 該如何捕獲錯誤呢?

async-to-js

其實已經有一個庫 async-to-js 已經幫我們做了這件事,我們可以看看它是怎麼做的,它的原始碼只有 短短十幾行 ,我們應該讀讀它的原始碼,學學它的思想

原始碼很簡單

/**
 * @param { Promise } 傳進去的請求函式
 * @param { Object= } errorExt - 擴充錯誤物件
 * @return { Promise } 返回一個Promise
 */
export function to(
  promise,
  errorExt
) {
  return promise
    .then(data => [null, data])
    .catch(err => {
      if (errorExt) {
        const parsedError = Object.assign({}, err, errorExt)
        return [parsedError, undefined]
      }

      return [err, undefined]
    })
}

export default to
原始碼總結: to 函式返回一個Promise且值是一個陣列,陣列之中有兩個元素,如果索引為 0 的元素不為空值,說明該請求報錯,如果索引 0 的元素為空值說明該請求沒有報錯,也就是成功。

使用很簡單

我們該怎麼去使用這個 to 函式呢?其實很簡單,還是剛剛的例子

const handleLogin = async () => {
  const [resErr, res] = await to(request('/basic/login', {
    usename: 'sunshine',
    password: '123456'
  }))
  if (resErr) {
    // fail do somthing
    return
  }
  const [userErr, info] = await to(request('/basic/getuserinfo', {
    id: res.id
  }))
  if (userErr) {
    // fail do somthing
    return
  }
  this.userInfo = info
}

所以說,偶爾看看一些庫的原始碼,還是能學到東西的!!!

結語

我是林三心,一個熱心的前端菜鳥程式設計師。如果你上進,喜歡前端,想學習前端,那我們們可以交朋友,一起摸魚哈哈,摸魚群,加我請備註【思否】

image.png

相關文章