點燈坊

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

使用 interval() 取代 setInterval()

Sam Xiao's Avatar 2021-04-29

setInterval() 為實務上常用 Function,但可惜其並非 Curry Function,不方便 Function Pipeline,interval()setInterval() 的 Curry 化版本。

Version

Vue 3.0.5
Wink-fp 1.23.7

Vue

interval000

每一秒中會更新 count 並顯示。

<template>
  {{ count }}
</template>

<script setup>
ref: count = 0

setInterval(() => count++, 1000)
</script>

第 6 行

ref: count = 0

使用 ref sugar 定義 count state。

第 8 行

setInterval(() => count++, 1000)

使用 setInterval() 每一秒鐘對 count 做遞增。

interval()

interval000

結果不變,但使用 interval() 改寫。

<template>
  {{ count }}
</template>

<script setup>
import { ref } from 'vue'
import { read, write } from 'vue3-fp'
import { pipe, always, inc } from 'ramda'

let interval = ms => f => setInterval(f, ms)

let count = ref(0)

let incCount = pipe(
  read(count),
  inc,
  write(count)
)

pipe(
  always(incCount),
  interval(1000)
)()
</script>

14 行

let incCount = pipe(
  read(count),
  inc,
  write(count)
)

使用 pipe() 組合 incCount()

  • read(count):讀取 count state
  • inc:對值遞增
  • write(count):寫入 count state

20 行

pipe(
  always(incCount),
  interval(1000)
)()

使用 pipe() 組合 IIFE:

  • always(incCount):準備 incCount() 為 argument 傳入 interval()
  • interval(1000):每一秒鐘執行 incCount() 一次

10 行

let interval = ms => f => setInterval(f, ms)

若要以 Function Pipeline 組合 setInterval(),會發現 setInterval() 並非 curry function 所以很難組合,所以另外建立 curry 版本的 interval(),並將 argument 順序顛倒方便使用。

Wink-fp

interval000

<template>
  {{ count }}
</template>

<script setup>
import { ref } from 'vue'
import { read, write } from 'vue3-fp'
import { pipe, always, inc } from 'ramda'
import { interval } from 'wink-fp'

let count = ref(0)

let incCount = pipe(
  read(count),
  inc,
  write(count)
)

pipe(
  always(incCount),
  interval(1000)
)()
</script>

第 9 行

import { interval } from 'wink-fp'

Wink-fp 已經內建 interval() 可直接使用。

interval()
Number -> () -> * -> Number
setInterval() 的 curry function 版本

Number:傳入 minisecond

() -> *;傳入執行 side effect 的 function

Number:回傳 interval id

Conclusion

  • interval() 很適合在 Function Pipeline 內使用,只要將普通 function 傳入 always(),再組合 interval() 即可

Reference

MDN, WindowOrWorkerGlobalScope.setInterval()