解決代碼中重複的捕獲 promise 錯誤的 try catch 語句

promise

promise 的出現,提供了優雅的異步解決方式,可是,多個連續繼發 promise 寫法依然繁瑣。react

let promise = new Promise(function(resolve, reject){
  // ...
  if(/* 異步任務執行成功 */) {
    resolve(value)
  } else {
    reject(error)
  }
})

promise.then(v => {}).catch(e => {})
複製代碼

async

es6 以後又新增了 async 函數來優化異步寫法,語義化更明確,寫法更優雅,可是錯誤捕獲比較麻煩,通常都得使用 try catch 來捕獲錯誤,具體優勢參考阮老師博客 async 函數es6

function promiseFunc = function(){
  return new Promise(function(resolve, reject){
    // ...
    if(/* 異步任務執行成功 */) {
      resolve(value)
    } else {
      reject(error)
    }
  })
}

async func(){
  let res = await promiseFunc()
}

// 錯誤捕獲
async func(){
  try{
    let res = await promiseFunc()
  }catch(err){
    alert(err)
  }
}

複製代碼

錯誤捕獲優化

以下是工做中 react + mobx 項目中 action 的代碼後端

class Actions {
  @action
  async deleteModel(params) {
    try {
      await this.post(apis.API_DEPLOY_DELETE, params)
      this.getDeployList(this.store.searchParams)
    } catch (e) {
      message.error(e.message || '出錯了!請稍後重試')
    }
  }

  @action
  async getDirChain(params) {
    try {
      let r = await this.post(apis.API_DEPLOY_DIR_CHAIN, params)
      runInAction(() => {
        this.store.dirChain = r
      })
    } catch (e) {
      message.error(e.message || '出錯了!請稍後重試')
    }
  }

}
複製代碼

如上代碼,兩個 action 都是向後端異步請求數據, 每一個 action 函數中都用了 try catch 函數,這樣重複寫了幾十個 action 函數api

必須幹掉 try catchpromise

錯誤捕獲裝飾器嘗試

裝飾器簡潔方便,首先嚐試, class 方法裝飾器函數以下app

const tryCatch = msg => (target, name, descriptor) => {
  const original = descriptor.value
  if (typeof original === 'function') {
    descriptor.value = async function(...args) {
      try {
        const result = await original.apply(this, args)
        return result
      } catch (e) {
        message.error(e.message || msg || '出錯了!請稍後重試')
      }
    }
  }
  return descriptor
}
複製代碼

如上代碼,封裝 tryCatch 裝飾器來對每一個 action 函數添加 try catch 錯誤捕獲。異步

屬性方法裝飾器中async

  • target 指向 class 實例
  • name 是被裝飾的方法名
  • descriptor 是方法的屬性修飾符

咱們能夠經過 descriptor.value 獲取到被裝飾的方法,在 try catch 中執行函數,捕獲錯誤或者返回結果函數

爲了靈活提示錯誤信息,裝飾器參數 msg 用來傳入自定義提示文本post

  • 用法(該用法是錯誤的)
@tryCatch // @tryCatch('運行出錯')
@action
async getDirChain(params) {
  let r = await this.post(apis.API_DEPLOY_DIR_CHAIN, params)
  runInAction(() => {
    this.store.dirChain = r
  })
}
複製代碼

以上對 async 函數進行錯誤捕獲的用法是錯誤的

如上的寫法是錯誤的,這種裝飾器只能對同步代碼產生做用,異步的是無效的,以前理解錯誤了

最後仍是解決了 try catch 問題

直接 async await 函數封裝就好了,簡單的問題想複雜了。。。

定義請求執行公共函數

/** * @param {string} method request method; ('get', 'post') * @param {string} api request url * @param {object} params payload * @memberof BaseActions */
request = async (method, api, params = {}) => {
  const requestFunc = async () => {
    let r = null
    try {
      r = await this[method](api, params)
    } catch (e) {
      message.error(e.message)
    }
    return r
  }

  return await requestFunc()
}
複製代碼

原有包含 try catch 重複代碼函數修改

@action
async getDirChain(params) {
  let r = await this.request('get', apis.API_DEPLOY_DIR_CHAIN, params)
  r && runInAction(() => this.store.dirChain = r)
}
複製代碼

終於不用不停寫重複代碼了。。。

相關文章
相關標籤/搜索