拋棄trycatch,用go的思想去處理js異常

語言: CN / TW / HK

theme: github

errors

錯誤處理在程式設計中是不可避免的一部分,在程式開發過程中,不可必要的會出現各種的錯誤,是人為也可能是失誤,任何不可預料的可能都會發生

為了更好的保證程式的健壯性和穩定性

我們必須要對錯誤處理有更好的認識

最近迷上了golang的錯誤處理哲學,希望由淺入深的總結一下自己的思考和看得見的思考

👀 用 error 表示可能出現的錯誤,用throw強制丟擲錯誤

通常情況下 錯誤處理的方式無非不過兩種

  • 泛處理
  • 精處理

其實都很好理解

``` // 虛擬碼

try { const file = await readFile('../file')

const content = filterContent(file)

} catch (e) { alert('xxxx',e.msg) } ```

泛處理指的是對所有可能的錯誤都使用相同的處理方式,比如在程式碼中使用相同統一的錯誤提示資訊

這種方式適用於一些簡單的,不太可能發生的錯誤,不如檔案不存在,網路連線超時等。

對於更加複雜的錯誤,應該使用精處理,即根據具體情況對不同型別的錯誤進行特定的處理

```

const [readErr,readFile] = await readFile('../file')

if (readErr) { // 處理讀取錯誤 return }

const [filterErr,filterContent] = filterContent(readFile)

if (filterErr) { // 處理過濾錯誤 return } ```

精處理可以讓我們把控計劃的每一步,問題也很顯然暴露了出來,過於麻煩

在實際開發當中,我們需要根據實際情況選擇適當的方式進行錯誤處理。

由於本人是精處理分子,基於此開發了一個js版本的errors

如何定義一個錯誤

``` import { Errors } from '@memo28/utils'

Errors.News('err') ```

如何給一個錯誤分類

``` import { Errors } from '@memo28/utils'

Errors.News('err', { classify: 1 }) ```

如何判斷兩個錯誤是相同型別

``` import { Errors } from '@memo28/utils'

Errors.As(Errors.News('err', { classify: 1 }), Errors.News('err2', { classify: 1 })) // true

Errors.As(Errors.News('err', { classify: 1 }), Errors.News('err2', { classify: 2 })) // false ```

一個錯誤包含了哪些資訊?

``` Errors.New('as').info() // { msg: 'as' , classify: undefined }

Errors.New('as').trace() // 列印呼叫棧

Errors.New('as').unWrap() // 'as' ```

最佳實踐

```ts import { AnomalousChain, panicProcessing } from '@memo28/utils'

class A extends AnomalousChain { // 定義錯誤處理函式, // 當每次執行的被 panicProcessing 裝飾器包裝過的函式都會檢查 是否存在 this.errors 是否為 ErrorsNewResult 型別 // 如果為 ErrorsNewResult 型別則 呼叫 panicProcessing的onError回撥 和 skip函式 skip(errors: ErrorsNewResult | null): this { console.log(errors?.info().msg) return this }

@panicProcessing() addOne(): this { console.log('run one') super.setErrors(Errors.New('run one errors')) return this }

@panicProcessing({ // 在 skip 前執行 onError(error) { console.log(error.unWrap()) }, // onRecover 從錯誤中恢復, 當返回的是true時 繼續執行addTwo內邏輯,反之 // onRecover(erros) { // return true // }, }) addTwo(): this { console.log('run two') return this } } new A().addOne().addTwo()

// output run one run one errors // in onError run one errors // in skip fn

```