點燈坊

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

使用 resolve() 建立 Fulfilled Promise

Sam Xiao's Avatar 2020-08-06

實務上我們可能累積了很多 Synchronous Function,但現在想轉成 Asynchronous Function 改回傳 Promise,這種常見的需求該如何實現呢 ?

Version

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

Async

let f = async x => x + 1

f(1) // ?

在 arrow function 前加上 ES2017 的 async 之後,inc() 搖身一變成為 asynchronous function,改回傳 Promise。

resolve000

Promise.resolve()

let f = x => Promise.resolve(x + 1)

f(1) // ?

async 算 syntatic sugar,實際上使用 Promise.resolve()x + 1 回傳值轉成 Promise。

resolve001

Ramda

import { pipe, inc, bind } from 'ramda'

let resolve = bind(Promise.resolve, Promise)

let f = pipe(
  inc,
  resolve
)

f(1) // ?

由以上範例可發現,實際上是先經過 x => x + 1 的運算,再將結果傳給 Promise.resolve() 轉成 Promise,這是一個 pipeline 過程。

x => x + 1 是很普通的 synchronous function,如 Ramda 早已提供 inc(),可直接使用。

既然 Ramda 有提供 inc(),又有 pipeline 本質,獨缺 resolve() 就可 pipeline,我們可自行建立使用 bind()Promise.resolve() static method 轉成 resolve() free function,如此就能使用 pipe()inc()resolve() 串起來。

resolve002

Wink-fp

import { pipe, inc } from 'ramda'
import { resolve } from 'wink-fp'

let f = pipe(
  inc,
  resolve
)

f(1) // ?

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

resolve()
a -> Promise a
將任意值包成 Fulfilled Promise

a:data 為任意值

Promise a:包成 Promise 回傳

resolve003

Conclusion

  • ECMAScript 很多 API 可能不適合 Function Pipeline,但我們可以使用 invoker()bind() 包成 free function
  • 透過 function 化的 resolve(),我們就可組合既有的 synchronous function 產生 asynchronous function

Reference

Ramda, inc()
Ramda, pipe()
Ramda, bind()