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