JavaScript中async await更優(yōu)雅的錯(cuò)誤處理方式
背景
團(tuán)隊(duì)來了新的小伙伴,發(fā)現(xiàn)我們的團(tuán)隊(duì)代碼規(guī)范中,要給 async await 添加 try...catch。他感覺很疑惑,假如有很多個(gè)(不集中),那不是要加很多個(gè)地方?那不是很不優(yōu)雅?
為什么要錯(cuò)誤處理
JavaScript 是一個(gè)單線程的語言,假如不加 try ...catch ,會(huì)導(dǎo)致直接報(bào)錯(cuò)無法繼續(xù)執(zhí)行。當(dāng)然不意味著你代碼中一定要用 try...catch 包住,使用 try...catch 意味著你知道這個(gè)位置代碼很可能出現(xiàn)報(bào)錯(cuò),所以你使用了 try...catch 進(jìn)行捕獲處理,并讓程序繼續(xù)執(zhí)行。
我理解我們一般在執(zhí)行 async await 的時(shí)候,一般運(yùn)行在異步的場景下,這種場景一般不應(yīng)該阻塞流程的進(jìn)行,所以推薦使用了 try...catch 的處理。
async await 更優(yōu)雅的錯(cuò)誤處理
但確實(shí)如那位同事所說,加 try...catch 并不是一個(gè)很優(yōu)雅的行為。所以我 Google 了一下,發(fā)現(xiàn) How to write async await without try-catch blocks in Javascript 這篇文章中提到了一種更優(yōu)雅的方法處理,并封裝成了一個(gè)庫——await-to-js。這個(gè)庫只有一個(gè) function,我們完全可以將這個(gè)函數(shù)運(yùn)用到我們的業(yè)務(wù)中,如下所示:
/**
* @param { Promise } promise
* @param { Object= } errorExt - Additional Information you can pass to the err object
* @return { Promise }
*/
export function to<T, U = Error> (
promise: Promise<T>,
errorExt?: object
): Promise<[U, undefined] | [null, T]> {
return promise
.then<[null, T]>((data: T) => [null, data]) // 執(zhí)行成功,返回?cái)?shù)組第一項(xiàng)為 null。第二個(gè)是結(jié)果。
.catch<[U, undefined]>((err: U) => {
if (errorExt) {
Object.assign(err, errorExt);
}
return [err, undefined]; // 執(zhí)行失敗,返回?cái)?shù)組第一項(xiàng)為錯(cuò)誤信息,第二項(xiàng)為 undefined
});
}
export default to;
這里需要有一個(gè)前置的知識(shí)點(diǎn):await 是在等待一個(gè) Promise 的返回值。
正常情況下,await 命令后面是一個(gè) Promise 對(duì)象,返回該對(duì)象的結(jié)果。如果不是 Promise 對(duì)象,就直接返回對(duì)應(yīng)的值。
所以我們只需要利用 Promise 的特性,分別在 promise.then 和 promise.catch 中返回不同的數(shù)組,其中 fulfilled 的時(shí)候返回?cái)?shù)組第一項(xiàng)為 null,第二個(gè)是結(jié)果。rejected 的時(shí)候,返回?cái)?shù)組第一項(xiàng)為錯(cuò)誤信息,第二項(xiàng)為 undefined。使用的時(shí)候,判斷第一項(xiàng)是否為空,即可知道是否有錯(cuò)誤,具體使用如下:
import to from 'await-to-js';
// If you use CommonJS (i.e NodeJS environment), it should be:
// const to = require('await-to-js').default;
async function asyncTaskWithCb(cb) {
let err, user, savedTask, notification;
[ 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) {
[ err ] = await to(NotificationService.sendNotification(user.id, 'Task Created'));
if(err) return cb('Error while sending notification');
}
if(savedTask.assignedUser.id !== user.id) {
[ err, notification ] = await to(NotificationService.sendNotification(savedTask.assignedUser.id, 'Task was created for you'));
if(err) return cb('Error while sending notification');
}
cb(null, savedTask);
}
小結(jié)
async await 中添加錯(cuò)誤處理個(gè)人認(rèn)為是有必要的,但方案不僅僅只有 try...catch。利用 async await 和 Promise 的特性,我們可以更加優(yōu)雅的處理 async await 的錯(cuò)誤。
總結(jié)
到此這篇關(guān)于JavaScript中async await更優(yōu)雅的錯(cuò)誤處理方式的文章就介紹到這了,更多相關(guān)async await優(yōu)雅錯(cuò)誤處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript面向?qū)ο笕筇卣髦鄳B(tài)實(shí)例詳解
這篇文章主要介紹了javascript面向?qū)ο笕筇卣髦鄳B(tài),結(jié)合實(shí)例形式詳細(xì)分析了javascript面向?qū)ο蟪绦蛟O(shè)計(jì)中多態(tài)的概念、原理,并結(jié)合實(shí)例形式總結(jié)了多態(tài)的實(shí)現(xiàn)方法與使用技巧,需要的朋友可以參考下2019-07-07
解決ie11 SCRIPT5011:不能執(zhí)行已釋放Script的代碼問題
這篇文章主要介紹了ie11 SCRIPT5011:不能執(zhí)行已釋放Script的代碼 ,需要的朋友可以參考下2019-05-05
javascript HTML5文件上傳FileReader API
這篇文章主要介紹了javascript HTML5文件上傳FileReader API的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-04-04
淺談javascript中執(zhí)行環(huán)境(作用域)與作用域鏈
本文主要介紹了javascript中執(zhí)行環(huán)境(作用域)與作用域鏈,并在文章結(jié)尾處做出了總結(jié),感興趣的朋友可以看下2016-12-12
JavaScript實(shí)戰(zhàn)(原生range和自定義特效)簡單實(shí)例
下面小編就為大家?guī)硪黄狫avaScript實(shí)戰(zhàn)(原生range和自定義特效)簡單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-08-08
JavaScript對(duì)象訪問器的工作原理及使用方法
今天來聊一下JavaScript中的對(duì)象訪問器,JavaScript的主要功能之一是能夠定義對(duì)象,這些對(duì)象可以封裝屬性和方法,本文將深入探討 JavaScript 對(duì)象訪問器是什么、它是如何工作的以及使用對(duì)象訪問器的作用,需要的朋友可以參考下2024-06-06

