async/await 如何優美的處理異常?

itKingOne發表於2018-06-07

本著一種學習的態度寫了此話題,如有不妥之處還請各位大牛多多指點.

Purpose: 此解決方案,可以避免業務程式碼中出現大量的try/catch, 眾所周知try/catch對效能方面有一定的影響,另一方面try/catch在Node.js >= v8.3.0以後對效能的損耗是可以忽略不計的.

try/catch具體文獻: However for Node 8.3+ the performance hit of calling a function inside a try block is negligible.

1. try/catch方法處理異常

async updateArticleById(ctx, next){
		 let id = ctx.params["id"];
       let body = ctx.request.body;
       try {
           let ret = await Services.admin.updateArticle(id, body);
           ctx.body = {ret: 0, data: ret};
       } catch(e) {
           ctx.body = {ret: 1, data: null, err: e.message || e.stack};
       }
}
  • 以上捕獲異常是使用try/catch的方式來處理,因為await後面跟著的是Promise物件,當有異常的情況下會被Promise物件的內部
  • catch捕獲,而await就是一個then的語法糖,並不會捕獲異常, 那就需要使用try/catch來捕獲異常,並進行相應的邏輯處理。

2. 封裝異常處理函式

  • 知道了上面異常會被Promise物件自身的catch捕獲異常,可以使用下面的解決方案 to.js
module.exports = (promise) => {
   if(!promise || !Promise.prototype.isPrototypeOf(promise)){
       return new Promise((resolve, reject)=>{
           reject(new Error("requires promises as the param"));
       }).catch((err)=>{
           return [err, null];
       });
   }
   return promise.then(function(){
       return [null, ...arguments];
   }).catch(err => {
       return [err, null];
   });
};

格式[error, …result]

  • 採用類似Golang風格的錯誤返回方式, 這裡指定第一個引數為錯誤引數,後面為正常返回結果
  • if塊是用來處理非法引數,並返回錯誤[err, null]
  • await後面如果是一個promise物件,那麼await的任務就是在等待promise.resolve,而to.js就是主動去呼叫then和catch,主動處理並重新封裝結果,並且在then或是catch裡面繼續返回封裝後的資料,返回值對於await來說仍然是一個promise物件,然而resolve的值卻是一個可迭代的物件[error, …result]

這個可迭代的物件如何使用 ?

async updateArticleById(ctx, next){
       let body = ctx.request.body;
       let id = ctx.request.params["id"];
       let [err, ret] = await ctx.app.utils.to(Services.admin.updateArticleById(id, body));
       if(err) {
           return ctx.body = {ret: 1, data: null, err: err};
       }

       ctx.body = {ret: 0, data: ret};
   }

相關文章