您好,登錄后才能下訂單哦!
本篇內容主要講解“ javascript中Dima去除try-catch的方法是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“ javascript中Dima去除try-catch的方法是什么”吧!
Dima 去除 try-catch 的方法
當然套路依舊,Dima 講到了回調地獄,Promise 鏈并最終引出了 async/await。而在處理錯誤的時候,他并不喜歡 try-catch 的方式,所以寫了一個 to(promise) 來對 Promise 進行封裝,輔以解構語法,實現了同步寫法但類似 Node 錯誤標準的代碼。摘抄代碼如下
// to.js export default function to(promise) { return promise .then(data => { return [null, data]; }) .catch(err => [err]); }
應用示例:
import to from "./to.js"; async function asyncTask(cb) { let err, user, savedTask; [err, user] = await to(UserModel.findById(1)); if (!user) return cb("No user found"); [err, savedTask] = await to(TaskModel({ userId: user.id, name: "Demo Task" })); if (err) return cb("Error occurred while saving task"); if (user.notificationsEnabled) { const [err] = await to(NotificationService.sendNotification(user.id, "Task Created")); if (err) return cb("Error while sending notification"); } cb(null, savedTask); }
Dima 的辦法讓人產生的了熟悉的感覺,Node 的回調中不是經常都這樣寫嗎?
(err, data) => { if (err) { // deal with error } else { // deal with data } }
所以這個方法真的很有意思。不過回過頭來想一想,這段代碼中每當遇到錯誤,都是將錯誤消息通過 cb() 調用推出去,同時中斷后續過程。像這種中斷式的錯誤處理,其實正適合采用 try-catch。
使用 try-catch 改寫上面的代碼
要用 try-catch 改寫上面的代碼,首先要去掉 to() 封裝。這樣,一旦發生錯誤,需要使用 Promise.prototype.catch() 進行捕捉,或者使用 try-catch 對 await promise 語句進行捕捉。捕捉到的,當然是每個業務代碼里 reject 出來的 err。
然而注意,上面的代碼中并沒有直接使用 err,而是使用了自定義的錯誤消息。所以需要對 reject 出來的 err 進一步處理成指定的錯誤消息。當然這難不到誰,比如
someAsync().catch(err => Project.reject("specified message"));
然后再最外層加上 try-catch 就好。所以改寫之后的代碼是:
async function asyncTask(cb) { try { const user = await UserModel.findById(1) .catch(err => Promise.reject("No user found")); const savedTask = await TaskModel({ userId: user.id, name: "Demo Task" }) .catch(err => Promise.reject("Error occurred while saving task")); if (user.notificationsEnabled) { await NotificationService.sendNotification(user.id, "Task Created") .catch(err => Promise.reject("Error while sending notification")); } cb(null, savedTask); } catch (err) { cb(err); } }
上面這段代碼,從代碼量上來說,并沒有比 Dima 的代碼減少了多少工作量,只是去掉了大量 if (err) {} 結構。不習慣使用 try-catch 的程序員找找不到中斷點,但習慣了 try-catch 的程序員都知道,業務過程中一旦發生錯誤(異步代碼里指 reject),代碼就會跳到 catch 塊去處理 reject 出來的值。
但是,一般業務代碼 reject 出來的信息通常都是有用的。假如上面的每個業務 reject 出來的 err 本身就是錯誤消息,那么,用 Dima 的模式,仍然需要寫
if (err) return cb(err);
而用 try-catch 的模式,就簡單多了
async function asyncTask(cb) { try { const user = await UserModel.findById(1); const savedTask = await TaskModel({ userId: user.id, name: "Demo Task" }); if (user.notificationsEnabled) { await NotificationService.sendNotification(user.id, "Task Created"); } cb(null, savedTask); } catch (err) { cb(err); } }
為什么?因為在 Dima 的模式中,if (err) 實際上處理了兩個業務:一是捕捉會引起中斷的 err ,并將其轉換為錯誤消息,二是通過 return 中斷業務過程。所以當 err 轉換為錯誤消息這一過程不再需要的時候,這種捕捉中斷再重新引起中斷的處理主顯得多余了。
繼續改進
用函數表達式改善 try-catch 邏輯
當然還有改進的空間,比如 try {} 塊中的代碼比較長,會造成閱讀不太方便,try-catch 的邏輯有被“切斷”的感覺。這種情況下可以使用函數表達式來改善
async function asyncTask(cb) { async function process() { const user = await UserModel.findById(1); const savedTask = await TaskModel({ userId: user.id, name: "Demo Task" }); if (user.notificationsEnabled) { await NotificationService.sendNotification(user.id, "Task Created"); } return savedTask; } try { cb(null, await process()); } catch (err) { cb(err); } }
如果對錯誤的處理代碼比較長,也可以寫成單獨的函數表達式。
如果過程中每一步的錯誤處理邏輯不同怎么辦
如果發生錯誤,不再轉換為錯誤消息,而是特定的錯誤處理邏輯,怎么辦?
思考一下,我們用字符串來表示錯誤消息,以后可以通過 console.log() 來處理處理。而邏輯,最適合的表示當然是函數表達式,最終可以通過調用來進行統一處理
async function asyncTask(cb) { async function process() { const user = await UserModel.findById(1) .catch(err => Promise.reject(() => { // deal with error on looking for the user return "No user found"; })); const savedTask = await TaskModel({ userId: user.id, name: "Demo Task" }) .catch(err => Promise.reject(() => { // making model error // deal with it return err === 1 ? "Error occurred while saving task" : "Error occurred while making model"; })); if (user.notificationsEnabled) { await NotificationService.sendNotification(user.id, "Task Created") .catch(err => Promise.reject(() => { // just print a message logger.log(err); return "Error while sending notification"; })); } return savedTask; } try { cb(null, await process()); } catch (func) { cb(func()); } }
甚至還可以處理更復雜的情況
現在應該都知道 .catch(err => Promise.reject(xx)),這里的 xx 就是 try-catch 的 catch 塊捕捉到的對象,所以如果不同的業務 reject 出來不同的對象,比如有些是函數(表示錯誤處理邏輯),有些是字符串(表示錯誤消息),有些是數字(表示錯誤代碼)——其實只需要改 catch 塊就行
try { // ... } catch(something) { switch (typeof something) { case "string": // show message something break; case "function": something(); break; case "number": // look up something as code // and show correlative message break; default: // deal with unknown error } }
到此,相信大家對“ javascript中Dima去除try-catch的方法是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。