點燈坊

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

使用 reject() 建立 Rejected Promise

Sam Xiao's Avatar 2020-08-06

reject()Promise.reject() 的 Free Function 版本,特別適合 Function Pipeline。

Version

macOS Catalina 10.15.6
VS Code 1.47.3
Quokka 1.0.312
Wink-fp 1.20.71

Promise.reject()

let f = () => Promise.resolve('Hello World')

f()
  .then(x => console.log(x))
  .then(() => Promise.reject('Something wrong'))
  .catch(e => console.error(e))

若想在 Fulfilled Handler 內自行建立 Rejected Promise,可由 Promise.reject() 建立 Rejected Promise,並在 catch() 捕捉。

reject002

Throw

let f = () => Promise.resolve('Hello World')

f()
  .then(x => console.log(x))
  .then(() => { throw 'Something wrong' })
  .catch(e => console.error(e))

也可在 Fulfilled Handler 中直接使用 throw 建立 Rejected Promise,其中 throw 就是 Promise.reject() 的 syntatic sugar。

reject003

Try Catch

let f = async () => 'Hello World'

try {
  let x = await f()
  console.log(x)
  throw 'Something wrong'
} catch(e) {
  console.error(e)
}

throw 除了能用在 Fulfilled Handler 外,也能用在 try catch 中,如此更符合 Imperative 與 Synchronous 習慣。

但別忘了 throw 是 syntatic sugar,當 throw 搭配 async await 時,它產生的是Rejected Promise。

reject004

Function Pipeline

import { pipe, andThen , otherwise, always, bind } from 'ramda'
import { resolve, log, error } from 'wink-fp'

let f = () => resolve('Hello World')

let reject = bind(Promise.reject, Promise)

pipe(
  f,
  andThen(log),
  andThen(always('Something wrong')),
  andThen(reject),
  otherwise(error)
)()

若想改以 FP 實現 promise chain,可搭配 Ramda 的 pipe()andThen()otherwise()

resolve()log()error() 則由 Wink-fp 提供。

第 6 行

let reject = bind(Promise.reject, Promise)

Ramda 並沒有提供 reject(),我們可自行建立使用 bind()Promise.reject() static method 轉成 reject() free function,如此就能使用 pipe()reject() 串起來。

reject001

Wink-fp

import { otherwise, always, bind } from 'ramda'
import { pipeP, resolve, reject, log, error } from 'wink-fp'

let f = () => resolve('Hello World')

pipeP(
  f,
  log,
  always('Something wrong'),
  reject,
  otherwise(error)
)()

Wink-fp 已經提供 reject(),可直接使用。

reject()
a -> Promise a
將任意值包成 Rejected Promise

a:data 為任意值

Promise a:包成 promise 回傳

reject002

Conclusion

  • ECMAScript 很多 API 可能不適合 Function Pipeline,但我們可以使用 invoker()bind() 包成 free function
  • 透過 function 化的 reject(),我們就可組合其他 function 產生 Rejected Promise

Reference

MDN, Promise.reject()
Ramda, pipe()
Ramda, bind()