點燈坊

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

使用 async() 將 Sync Function 轉成 Async Function

Sam Xiao's Avatar 2020-03-28

ECMAScript 2015 引進 Promise,2017 引進 Async Await,至此 ECMAScript 才有 Async Function 概念,該如何將原本 Sync Function 轉成 Async Function 呢 ?

Version

macOS Catalina 10.15.4
VS Code 1.43.1
Quokka 1.0.284
Ramda 0.27.0
Wink-fp 1.20.62

Promise

let inc = x => x + 1
let incAsync = async x => x + 1

let f = x => incAsync(x)

f(1) // ?

inc() 為典型 sync function,incAsync() 則為 async function,雖然也是回傳 x + 1,但會包在 promise 內。

async002

Async Function

let inc = x => x + 1
let incAsync = async x => x + 1

let f = async x => await incAsync(x)

f(1) // ?

因為 incAsync() 回傳 promise,亦可改用 await 取出 promise 內部值,最後再使用 async 包成 promise。

async003

async1()

let inc = x => x + 1

let async1 = f => x => Promise.resolve(f(x))

let incAsync = async1(inc)

let f = async x => await incAsync(x)

f(1) // ?

Async function 畢竟是新觀念,ECMAScript 的 codebase 與 library 已經存在大量 sync function,能透過 higher order function 將既有 sync function 轉成 async function 嗎 ?

第 3 行

let async1 = f => x => Promise.resolve(f(x))

async1() higher order function 的第一個 argument 為 function,回傳新 function 並以 Promise.resolve() 包成 promise。

1 表示 unary function

第 5 行

let incAsync = async1(inc)

inc() 透過 async1() 轉換後即成為 incAsync() async function。

async005

let inc = x => x + 1

let async1 = f => async x => await f(x)

let incAsync = async1(inc)

let f = async x => await incAsync(x)

f(1) // ?

第 3 行

let async1 = f => async x => await f(x)

async1() higher order function 亦可使用 async await 實作。

async004

Wink-fp

import { inc } from 'ramda'
import { async1, pipeP } from 'wink-fp'

let incAsync = async1(inc)

let f = pipeP(
  incAsync,
  incAsync,
  incAsync
)

f(1) // ?

Wink-fp 已經支援 async1() 可直接使用。

async1()
(a -> b) -> (a -> Promise b)
將 sync unary function 轉成 async unary function

(a -> b):data 為 sync unary function

(a -> Promise b):回傳 async unary function

async000

async2()

import { add } from 'ramda'
import { pipeP, async2 } from 'wink-fp'

let addAsync = async2(add)

let f = pipeP(
  addAsync(2),
  addAsync(3),
  addAsync(4)
)

f(1) // ?

Wink-fp 亦提供 async2(),專門負責將 sync binary function 轉成 async binary function。

async2()
(a -> b -> c) -> (a -> b -> Promise c)
將 sync binary function 轉成 async binary function

(a -> b -> c):data 為 sync binary function

(a -> b -> Promise c):回傳 async binary function

async001

Conclusion

  • Wink-fp 亦提供 async3() 專門負責 ternary function

Reference

Ramda, inc()
Ramda, add()