點燈坊

失くすものさえない今が強くなるチャンスよ

Promise Chan 之 Multiple Otherwise

Sam Xiao's Avatar 2021-08-07

雖然實務上 Promise Chain 大都只有一個 otherwise,但事實上也能同時有多個 otherwise,可繼續新的 Asynchornous Function,或者將 Error Handling 在不同 otherwise 分段處理。

Version

Ramda 0.27.1

Single Otherwise

import { pipe, andThen as then, otherwise, always as K } from 'ramda'
import { reject, resolve, log, error } from 'wink-fp'

let f = reject

let g = resolve

pipe (
  f,
  then (log),
  then (K (g (2))),
  then (log),
  otherwise (error)
) (1)

若 Function Pipeline 只有一個 otherwise,只要有一個 async function 回傳 Rejected,則後續的 async function 就不會執行。

otherwise000

Multiple Otherwise

import { pipe, andThen as then, otherwise, always as K } from 'ramda'
import { reject, resolve, log, error } from 'wink-fp'

let f = reject

let g = resolve

pipe (
  f,
  then (log),
  otherwise (error),
  then (K (g (2))),
  then (log),
  otherwise (error)
) (1)

若想每個 async function 不互相影響,儘管其中一個 async function 回傳 Rejected,也不會影響之後 async function 執行,可在每個 async function 之後加上 otherwise

因為 otherwise 回傳 Resolved,因此 Function Pipeline 得以繼續。

otherwise001

import { pipe, andThen as then, otherwise, always as K } from 'ramda'
import { reject, resolve, log, error } from 'wink-fp'

let f = reject

let g = resolve

pipe (
  f,
  then (log),
  otherwise (error)
) (1)

pipe (
  g,
  then (log),
  otherwise (error)
) (2)

也可以寫成多個 Function Pipleine,則各 async function 亦不會互相影響。

otherwise002

Rethrow

import { pipe, andThen as then, otherwise } from 'ramda'
import { reject, log, error } from 'wink-fp'

let f = reject

pipe (
  f,
  then (log),
  otherwise (log),
  otherwise (error)
) (1)

由於 otherwise 會回傳 Resolved,因此儘管寫了多個 otherwise,只有第一個 otherwise 會被執行。

otherwise003

import { pipe, andThen as then, otherwise } from 'ramda'
import { reject, log, error } from 'wink-fp'

let f = reject

pipe (
  f,
  then (log),
  otherwise (e => (log (e), reject (e))),
  otherwise (error)
) (1)

若想讓第二個 otherwise 也被執行,必須在第一個 otherwise 內重新回傳 Rejected。

Conclusion

  • 若要呼叫多個 API,且彼此不互相影響,儘管其中一個 API 失敗,剩下 API 也要繼續執行,則可使用 multiple otherwise 或者使用 multiple Function Pipeline 皆可
  • 實務上在處理 API 回傳的 Rejected 時,可將 reset state 寫在第一個 otherwise 並重新回傳 Rejected,並將處理 status code 寫在第二個 otherwise

Reference

Ramda, otherwise