若我們想延遲一段時間才產生 Promise,標準做法是 Promise Constructor 配上 Callback-based 的 setTimeout()
,事實上搭配 Promise-based 的 sleep()
之後, 能用更 Functional 方法實現。
Version
macOS Mojave 10.14.6
VS Code 1.38.1
Quokka 1.0.244
Ramda 0.26.1
Wink-fp 0.1.0
Imperative
let resolveAfter = ms => val => new Promise(
resolve => setTimeout(() => resolve(val), ms)
);
await resolveAfter(300)(2); // ?
欲實現 resolveAfter()
,第一個 argument 傳入延遲時間,第二個 argument 傳入 data,將在延遲一段時間後傳回 data 的 promise。
因為會使用 setTimeout()
延遲一段時間,ECMAScript 標準做法是使用 promise constructor 的 resolve()
,然後在 setTimeout()
的 callback 中呼叫 resolve()
產生 promise。
Pipeline
import { pipe, then, always } from 'ramda';
import { sleep, resolve } from 'wink-fp';
let resolveAfter = ms => val => pipe(
sleep,
then(always(val)),
then(resolve)
)(ms);
await resolveAfter(300)(2); // ?
事實上 setTimeout()
相當於 Wink-fp 的 sleep()
,由於 sleep()
回傳 promise,可改用 pipe()
將 sleep()
與 resolve()
串起來。
可將
sleep()
想成 promise-based 的setTimeout()
Point-free
import { useWith, flip, then, thunkify } from 'ramda';
import { sleep, resolve } from 'wink-fp';
let resolveAfter = useWith(
flip(then),
[sleep, thunkify(resolve)]
);
await resolveAfter(300)(2); // ?
也可將 resolveAfter()
進一步使用 useWith()
與 thunkify()
使其 point-free。
Wink-fp
import { resolveAfter } from 'wink-fp';
await resolveAfter(300)(2); // ?
事實上 Wink-fp 已經內建 resolveAfter()
,可直接使用。
resolveAfter()
Number -> a -> Promise a
延遲一段時間後產生 promise
Number
:延遲一段時間
a
:任意型別的 data
Promise a
:將 data 包成 promise 回傳
同理 Wink-fp 也提供
rejectAfter()
Conclusion
setTimeout()
為 callback-based function,也因此必須搭配 promise coustructor 的resolve()
,若改用 promise-based 的sleep()
,則可使用 Ramda 的pipe()
與then()
使其 pipeline,可再進一步使用useWith()
與thunkify()
使其 point-free