摘要:能夠捕獲非異步的異常。來(lái)匹配正常異常的情況。在中處理所有的異常如果出錯(cuò),則退出。所以,的模式使得異常處理變得非常簡(jiǎn)潔。自從年雙十一正式上線,累計(jì)處理了億錯(cuò)誤事件,付費(fèi)客戶有陽(yáng)光保險(xiǎn)核桃編程荔枝掌門(mén)對(duì)微脈青團(tuán)社等眾多品牌企業(yè)。
譯者按: 使用.catch()來(lái)捕獲所有的異常
原文: Async Await Error Handling in JavaScript
譯者: Fundebug
本文采用意譯,版權(quán)歸原作者所有
async/await 中的異常處理很讓人混亂。盡管有很多種方式來(lái)應(yīng)對(duì)async 函數(shù)的異常,但是連經(jīng)驗(yàn)豐富的開(kāi)發(fā)者有時(shí)候也會(huì)搞錯(cuò)。
假設(shè)你有一個(gè)叫做run()的異步函數(shù)。在本文中,我會(huì)描述 3 種方式來(lái)處理run()的異常情形: try/catch, Go 語(yǔ)言風(fēng)格, 函數(shù)調(diào)用的時(shí)候使用 catch()(即run().catch())。 我會(huì)跟你解釋為什么其實(shí)幾乎只需要catch()就足夠。
try/catch當(dāng)你第一次使用async/await, 你可能?chē)L試使用try/catch將每一個(gè) async 操作包圍起來(lái)。如果你await一個(gè)被 reject 的 Promise,JavaScript 會(huì)拋出一個(gè)可以被捕獲的錯(cuò)誤。
run(); async function run() { try { await Promise.reject(new Error("Oops!")); } catch (error) { error.message; // "Oops!" } }
try/catch 能夠捕獲非異步的異常。
run(); async function run() { const v = null; try { await Promise.resolve("foo"); v.thisWillThrow; } catch (error) { // "TypeError: Cannot read property "thisWillThrow" of null" error.message; } }
所以,只需要將所有的代碼邏輯都用 try/catch包圍起來(lái)就可以搞定?也不完全正確。下面的代碼會(huì)拋出unhandled promise rejection. await將一個(gè)被拒絕的 promise 轉(zhuǎn)換為可捕獲的錯(cuò)誤,但是 return 不行。
run(); async function run() { try { // 注意這里是return,不是await return Promise.reject(new Error("Oops!")); } catch (error) { // 代碼不會(huì)執(zhí)行到這里 } }
也不可能使用 return await來(lái)繞開(kāi)。
還有一個(gè)缺點(diǎn)就是使用了try/catch 之后,就很難用.的語(yǔ)法來(lái)進(jìn)行 Promise 鏈?zhǔn)浇M合了。
使用 Go 的語(yǔ)法另一個(gè)常見(jiàn)的方式就是使用then()將一個(gè)本來(lái)需要用catch()來(lái)捕獲并處理的 Promise 轉(zhuǎn)換為普通的 Promise。然后像 Go 語(yǔ)言中一樣,使用if(err)來(lái)處理異常。
run(); async function throwAnError() { throw new Error("Oops!"); } async function noError() { return 42; } async function run() { // The `.then(() => null, err => err)` 來(lái)匹配正常/異常的情況。如果正常情況,返回`null`;如果異常,返回`err` let err = await throwAnError().then(() => null, err => err); if (err != null) { err.message; // "Oops" } err = await noError().then(() => null, err => err); err; // null }
如果你真的想要同時(shí)返回 error 和正確的值,你可以完全假裝在用 Go 語(yǔ)言。
run(); async function throwAnError() { throw new Error("Oops!"); } async function noError() { return 42; } async function run() { // The `.then(v => [null, v], err => [err, null])` pattern // 你可以使用數(shù)組解構(gòu)來(lái)匹配err和返回值 let [err, res] = await throwAnError().then( v => [null, v], err => [err, null] ); if (err != null) { err.message; // "Oops" } err = await noError().then(v => [null, v], err => [err, null]); err; // null res; // 42 }
使用 Go 語(yǔ)言風(fēng)格的錯(cuò)誤處理并不能擺脫return無(wú)法捕獲的情況。而且還讓整個(gè)代碼更加的復(fù)雜,如果忘記if(err != null),就會(huì)出問(wèn)題。
總的來(lái)說(shuō),有兩大缺點(diǎn):
代碼極度重復(fù),每一個(gè)地方都少不了if (err != null) ,真的很累,而且容易漏掉;
run()函數(shù)中的非異步的錯(cuò)誤也無(wú)法處理;
總的來(lái)說(shuō),它并沒(méi)有比try/catch好多少。
在函數(shù)調(diào)用的時(shí)候使用catch()try/catch 和 Go 語(yǔ)言風(fēng)格的異常處理都有各自的使用場(chǎng)景,但是處理所有異常最好的方法是在run()函數(shù)的后面使用catch(),像這樣:run().catch()。換句話說(shuō),用一個(gè)catch()來(lái)處理run函數(shù)中的所有錯(cuò)誤,而不是針對(duì)run里面的每一種情況都去寫(xiě)代碼做相應(yīng)的處理。
run() .catch(function handleError(err) { err.message; // Oops! }) // 在handleError中處理所有的異常 // 如果handleError出錯(cuò),則退出。 .catch(err => { process.nextTick(() => { throw err; }); }); async function run() { await Promise.reject(new Error("Oops!")); }
記住,async 函數(shù)總是返回 promise。只要函數(shù)中有異常,Promise 會(huì) reject。而且,如果一個(gè) async 函數(shù)返回的是一個(gè) reject 的 Promise,那么這個(gè) Promise 依然會(huì)繼續(xù)被 reject。
run() .catch(function handleError(err) { err.message; // Oops! }) .catch(err => { process.nextTick(() => { throw err; }); }); async function run() { // 注意:這里使用了return,而不是await return Promise.reject(new Error("Oops!")); }
為什么使用run().catch()而不是將整個(gè)run()函數(shù)用try/catch包起來(lái)呢?我們首先來(lái)考慮一個(gè)情況:如果try/catch的catch部分有異常,我們應(yīng)該如何處理呢?只有一個(gè)方法:在catch里面接著使用try/catch。所以,run().catch()的模式使得異常處理變得非常簡(jiǎn)潔。
總結(jié)我們最好是全局的有一個(gè) errorHandler 來(lái)處理那些沒(méi)有考慮到的異常,比如使用run().catch(handleError),而不是在run()函數(shù)里面所有可能出錯(cuò)的地方加上try/catch。
關(guān)于FundebugFundebug專(zhuān)注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java線上應(yīng)用實(shí)時(shí)BUG監(jiān)控。 自從2016年雙十一正式上線,F(xiàn)undebug累計(jì)處理了10億+錯(cuò)誤事件,付費(fèi)客戶有陽(yáng)光保險(xiǎn)、核桃編程、荔枝FM、掌門(mén)1對(duì)1、微脈、青團(tuán)社等眾多品牌企業(yè)。歡迎大家免費(fèi)試用!
版權(quán)聲明轉(zhuǎn)載時(shí)請(qǐng)注明作者 Fundebug以及本文地址:https://blog.fundebug.com/2019/07/24/async-await-error-handling-in-js/
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/105970.html
摘要:這只是一個(gè)更優(yōu)雅的得到值的語(yǔ)句,它比更加容易閱讀和書(shū)寫(xiě)??偨Y(jié)放在一個(gè)函數(shù)前的有兩個(gè)作用使函數(shù)總是返回一個(gè)允許在這其中使用前面的關(guān)鍵字能夠使等待,直到處理結(jié)束。 Async/await 寫(xiě)在前面 渣渣新人的首篇外文文章翻譯??!存在錯(cuò)誤可能會(huì)很多,如有錯(cuò)誤,煩請(qǐng)各位大大指正出來(lái),感謝! 本篇為翻譯!本篇為翻譯!本篇為翻譯! 原文文章地址:https://javascript.info/a...
摘要:使用時(shí)也要注意范圍和層級(jí)。服務(wù)端配置服務(wù)端使用,最簡(jiǎn)單的方式是通過(guò)。云引擎是推出的服務(wù)器端運(yùn)行環(huán)境,支持和環(huán)境,功能強(qiáng)大而且目前免費(fèi),結(jié)合,使原本復(fù)雜的開(kāi)發(fā)工作變得簡(jiǎn)單高效。目前也支持和海外節(jié)點(diǎn),輕松滿足你的業(yè)務(wù)需求。 構(gòu)建一個(gè)應(yīng)用程序總是會(huì)面對(duì)異步調(diào)用,不論是在 Web 前端界面,還是 Node.js 服務(wù)端都是如此,JavaScript 里面處理異步調(diào)用一直是非常惡心的一件事情。以...
摘要:接下來(lái)介紹下異步編程六種方法。六生成器函數(shù)是提供的一種異步編程解決方案,語(yǔ)法行為與傳統(tǒng)函數(shù)完全不同,最大的特點(diǎn)就是可以控制函數(shù)的執(zhí)行。參考文章前端面試之道異步編程的種方法你不知道的中卷函數(shù)的含義和用法替代的個(gè)理由 前言 我們知道Javascript語(yǔ)言的執(zhí)行環(huán)境是單線程。也就是指一次只能完成一件任務(wù)。如果有多個(gè)任務(wù),就必須排隊(duì),前面一個(gè)任務(wù)完成,再執(zhí)行后面一個(gè)任務(wù)。 這種模式雖然實(shí)現(xiàn)起...
摘要:優(yōu)點(diǎn)簡(jiǎn)單粗暴,直接調(diào)用缺點(diǎn)兼容性不太好,不過(guò)的話都支持你可能不知道的前端知識(shí)點(diǎn)對(duì)象和的方法。下面從深層次剖析一下對(duì)于開(kāi)始的兩個(gè)賦值語(yǔ)句,,,相當(dāng)于,而顯然等于。同理可以分析第三個(gè)賦值語(yǔ)句 有些東西很好用,但是你未必知道;有些東西你可能用過(guò),但是你未必知道原理。 實(shí)現(xiàn)一個(gè)目的有多種途徑,俗話說(shuō),條條大路通羅馬。很多內(nèi)容來(lái)自平時(shí)的一些收集以及過(guò)往博客文章底下的精彩評(píng)論,收集整理拓展一波,發(fā)...
閱讀 2910·2021-11-19 09:40
閱讀 3760·2021-11-15 18:10
閱讀 3374·2021-11-11 16:55
閱讀 1326·2021-09-28 09:36
閱讀 1725·2021-09-22 15:52
閱讀 3427·2019-08-30 14:06
閱讀 1222·2019-08-29 13:29
閱讀 2364·2019-08-26 17:04