日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何优雅处理 async await 错误——解读小而美的 await-to-js 库

發(fā)布時間:2023/12/9 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何优雅处理 async await 错误——解读小而美的 await-to-js 库 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

大家好,我是若川。持續(xù)組織了5個月源碼共讀活動,感興趣的可以點此加我微信 ruochuan12?參與,每周大家一起學(xué)習(xí)200行左右的源碼,共同進(jìn)步。同時極力推薦訂閱我寫的《學(xué)習(xí)源碼整體架構(gòu)系列》?包含20余篇源碼文章。

這是源碼共讀活動第21期 await-to-js,優(yōu)雅的處理 async await 的 try-catch,讀者掘金@愛嘿嘿的小黑 的投稿。

1前言

學(xué)而不思則罔

最近有在讀一些比較優(yōu)秀的npm包的代碼,起因是感覺自己現(xiàn)在寫的代碼還是不夠規(guī)范,不夠簡潔。

可是我又不知道到底什么樣的代碼才算是比較的代碼,在進(jìn)行一番思考過后我認(rèn)為還是要站在巨人的肩膀上。

通過閱讀優(yōu)秀的源碼并從中學(xué)習(xí)如何寫出讓人覺得賞心悅目的代碼最后再寫文進(jìn)行章總結(jié)對整個學(xué)習(xí)的過程進(jìn)行一個梳理同時分享給其他人。

為什么要在開頭寫這么多呢?因為我需要為自己堅持下去找一個理由。這樣我才能乘風(fēng)破浪,一往無前。

話不多說,開始總結(jié)。

2JS異步編程進(jìn)化之路

回調(diào)地獄階段

在正式介紹await-to-js這個庫之前,讓我們先簡單的回顧一下有關(guān)于在JavaScript這門語言中,異步編程的進(jìn)化之路。在Promise沒出現(xiàn)之前,異步編程一直是困擾著前端工程師的一個大難題,當(dāng)時的前輩可能會經(jīng)常看到下面這種代碼。

function?AsyncTask()?{asyncFuncA(function(err,?resultA){if(err)?return?cb(err);asyncFuncB(function(err,?resultB){if(err)?return?cb(err);asyncFuncC(function(err,?resultC){if(err)?return?cb(err);//?And?so?it?goes....});});}); }

這種同時在縱向和橫向延伸的回調(diào)中嵌套著回調(diào)的代碼又被稱為回調(diào)地獄。可見這玩意讓人多么惡心,具體來說有以下這幾個缺點

  • 難以維護(hù)(看都不想看,還維護(hù)個**)

  • 難以捕捉到錯誤(一個一個找?) 總而言之,這個問題在當(dāng)時是很需要被解決的,所以在ES6中,出現(xiàn)了Promise。

Promise階段

Promise是一種優(yōu)雅的異步編程解決方案。從語法上來將,它是一個對象, 代表著一個異步操作最終完成或失敗,從語意上來講,它是承諾,承諾過一段時間給你一個結(jié)果。

由于它的原型存在then,catch,finally會返回一個新的promise所以可以允許我們鏈?zhǔn)秸{(diào)用,解決了傳統(tǒng)的回調(diào)地獄的問題。

由于它本身存在all方法,所以可以支持多個并發(fā)請求,獲取并發(fā)請求中數(shù)據(jù)。

有了Promise后,上面的代碼可以被寫成下面這樣。

function?asyncTask(cb)?{asyncFuncA.then(AsyncFuncB).then(AsyncFuncC).then(AsyncFuncD).then(data?=>?cb(null,?data).catch(err?=>?cb(err)); }

相比較于上面的回調(diào)地獄,使用Promise可以幫助我們讓代碼只在縱向發(fā)展,并且提供了處理錯誤的回調(diào)。顯然優(yōu)雅了很多。不過就算Promise已經(jīng)這么優(yōu)秀了,可是依然存在兩個每種不足的地方

  • 不夠同步(代碼依然會縱向延伸)

  • 不能給每一次異步操作都進(jìn)行錯誤處理 這也就是為什么ES7中會出現(xiàn)async/await,號稱異步編程的最后解決方案的原因了。

async/await

async 函數(shù)是 Generator 函數(shù)的語法糖。使用 關(guān)鍵字 async 來表示,在函數(shù)內(nèi)部使用 await 來表示異步。相較于 Generator,async 函數(shù)的改進(jìn)在于下面四點:

  • 內(nèi)置執(zhí)行器。Generator 函數(shù)的執(zhí)行必須依靠執(zhí)行器,而 async 函數(shù)自帶執(zhí)行器,調(diào)用方式跟普通函數(shù)的調(diào)用一樣

  • 更好的語義。async 和 await 相較于 * 和 yield 更加語義化

  • 更廣的適用性。co 模塊約定,yield 命令后面只能是 Thunk 函數(shù)或 Promise對象。而 async 函數(shù)的 await 命令后面則可以是 Promise 或者 原始類型的值(Number,string,boolean,但這時等同于同步操作)

  • 返回值是 Promise。async 函數(shù)返回值是 Promise 對象,比 Generator 函數(shù)返回的 Iterator 對象方便,可以直接使用 then() 方法進(jìn)行調(diào)用

此處總結(jié)參考自:理解async/await[1]

有了async/await,上面的代碼可以被改寫成下面這樣

function?async?asyncTask(cb)?{const?asyncFuncARes?=?await?asyncFuncA()const?asyncFuncBRes?=?await?asyncFuncB(asyncFuncARes)const?asyncFuncCRes?=?await?asyncFuncC(asyncFuncBRes) }

同時我們可以對每一次異步操作進(jìn)行錯誤處理

function?async?asyncTask(cb)?{try?{const?asyncFuncARes?=?await?asyncFuncA()}?catch(error)?{return?new?Error(error)}try?{const?asyncFuncBRes?=?await?asyncFuncB(asyncFuncARes)}?catch(error)?{return?new?Error(error)}try?{const?asyncFuncCRes?=?await?asyncFuncC(asyncFuncBRes)}?catch(error)?{return?new?Error(error)} }

這樣一來上面Promise存在的兩個每種不足的地方是不是就被優(yōu)化了呢?所以說async/await是JS中異步編寫的最后解決方案我個人覺得一點問題沒有,但是我不知道你看上面的代碼,每一次異步操作都要用try/catch進(jìn)行錯誤處理是不是感覺不夠方便不夠智能呢?

3await-to-js-小而美的npm包

基本用法

作者是這樣介紹這個庫的

Async await wrapper for easy error handling without try-catch。

中文翻譯過來就是

無需 try-catch 即可輕松處理錯誤的異步等待包裝器。

這里做個簡單的對比,之前我們在異步操作中處理錯誤的方法是這樣的

function?async?asyncTask()?{try?{const?asyncFuncARes?=?await?asyncFuncA()}?catch(error)?{return?new?Error(error)}try?{const?asyncFuncBRes?=?await?asyncFuncB(asyncFuncARes)}?catch(error)?{return?new?Error(error)}try?{const?asyncFuncCRes?=?await?asyncFuncC(asyncFuncBRes)}?catch(error)?{return?new?Error(error)} }

而用了await-to-js之后,我們可以這樣的處理錯誤

import?to?from?'./to.js'; function?async?asyncTask()?{const?[err,?asyncFuncARes]??=?await?to(asyncFuncA())if(err)?throw?new?(error);const?[err,?asyncFuncBRes]??=?await?tp(asyncFuncB(asyncFuncARes))if(err)?throw?new?(error);const?[err,?asyncFuncCRes]??=?await?to(asyncFuncC(asyncFuncBRes)if(err)?throw?new?(error); }

是不是簡潔多了呢?

作者究竟用了什么黑魔法?

你可能不信,源碼只有僅僅15行。

源碼分析

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]).catch<[U,?undefined]>((err:?U)?=>?{if?(errorExt)?{const?parsedError?=?Object.assign({},?err,?errorExt);return?[parsedError,?undefined];}return?[err,?undefined];}); }export?default?to;

上面這里是TS版的源碼,但是考慮到有些同學(xué)可能還沒接觸過TS,我著重分析一下下面這版JS版的源碼。

export?function?to(promise,?errorExt)?{return?promise.then((data)?=>?[null,?data]).catch((err)?=>?{if?(errorExt)?{const?parsedError?=?Object.assign({},?err,?errorExt);return?[parsedError,?undefined];}return?[err,?undefined];}); } export?default?to;

這里我們先拋開errorExt這個自定義的錯誤文本,核心代碼是這樣的

export?function?to(promise)?{return?promise.then((data)?=>?[null,?data])?//?成功,返回[null,響應(yīng)結(jié)果].catch((err)?=>?{return?[err,?undefined];?//?失敗,返回[錯誤信息,undefined]}); } export?default?to;

可以看出,其代碼的邏輯用中文解釋是這樣的

  • 無論成功還是失敗都返回一個數(shù)組,數(shù)組的第一項是和錯誤相關(guān)的,數(shù)組的第二項是和響結(jié)果相關(guān)的

  • 成功的話數(shù)組第一項也就是錯誤信息為空,數(shù)組第二項也就是響應(yīng)結(jié)果正常返回

  • 失敗的話數(shù)組第一項也就是錯誤信息為錯誤信息,數(shù)組第二項也就是響應(yīng)結(jié)果返回undefined

經(jīng)過上面的分析我們可以認(rèn)定,世界上沒有什么黑魔法,沒有你做不到,只有你想不到。

這里我們再來看函數(shù)to的第二個參數(shù)errorExt不難發(fā)現(xiàn),這玩意其實就是拿來用戶自定義錯誤信息的,通過Object.assign將正常返回的error和用戶自定義和合并到一個對象里面供用戶自己選擇。

4結(jié)語

源碼不可怕,可怕的是自己的面對未知的恐懼感。

敢于面對,敢于嘗試,才能更上一層樓。

繼續(xù)加油,少年。

關(guān)注我,vx:codebangbang,掘金:愛嘿嘿的小黑。

5參考資料

  • 倉庫地址:https://github.com/scopsy/await-to-js

  • 官方文章:How to write async await without try-catch blocks in Javascript[2]

參考資料

[1]

https://segmentfault.com/a/1190000010244279: https://link.juejin.cn?target=https%3A%2F%2Fsegmentfault.com%2Fa%2F1190000010244279

[2]

How to write async await without try-catch blocks in Javascript: https://blog.grossman.io/how-to-write-async-await-without-try-catch-blocks-in-javascript/


·················?若川簡介?·················

你好,我是若川,畢業(yè)于江西高校。現(xiàn)在是一名前端開發(fā)“工程師”。寫有《學(xué)習(xí)源碼整體架構(gòu)系列》20余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結(jié),已經(jīng)寫了7篇,點擊查看年度總結(jié)。
同時,最近組織了源碼共讀活動,幫助3000+前端人學(xué)會看源碼。公眾號愿景:幫助5年內(nèi)前端人走向前列。

識別方二維碼加我微信、拉你進(jìn)源碼共讀

今日話題

略。分享、收藏、點贊、在看我的文章就是對我最大的支持~

總結(jié)

以上是生活随笔為你收集整理的如何优雅处理 async await 错误——解读小而美的 await-to-js 库的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。