由於 pipe()
要求每個 Argument 都是 Function,因此實務上常遇到需組合出 () -> a
的需求,always()
與 thunkify()
皆可完成,但兩者觀念不太一樣。
Version
Vue 3.0.5
Ramda 0.27.1
Point-free
按下 Get Book
會從 API 獲得 title
與 price
。
<template>
<div>
<button @click="onClick">Get Book</button>
</div>
<div>
{{ title }} / {{ price }}
</div>
</template>
<script setup>
import { ref } from 'vue'
import { effect } from 'vue3-fp'
import { pipe, andThen as then, prop, otherwise } from 'ramda'
import getBook from '/src/api/getBook'
let title = ref('')
let price = ref('')
let onClick = pipe(
() => getBook(1),
then(prop('data')),
then(effect('title', title)),
then(effect('price', price)),
otherwise(console.error)
)
</script>
19 行
let onClick = pipe(
() => getBook(1),
then(prop('data')),
then(effect('title', title)),
then(effect('price', price)),
otherwise(console.error)
)
使用 pipe()
組合 onClick()
:
() => getBook(1)
:getBook()
為 API function,由於pipe()
要求每個 argument 都是 function,因此原本fetchBook(1)
要改成() => fetchBook(1)
成為 functionthen(prop('data'))
:getBook()
回傳為 Promise,因此要在then()
取得data
propthen(effect('title', title))
:將title
prop 寫入title
state,並回傳 Objectthen(effect('price', price))
:將price
prop 寫入price
state,並回傳 Objectotherwise(console.error)
:處理 Rejected Promise
always()
結果不變,但使用 always()
改寫。
<template>
<div>
<button @click="onClick">Get Book</button>
</div>
<div>
{{ title }} / {{ price }}
</div>
</template>
<script setup>
import { ref } from 'vue'
import { effect } from 'vue3-fp'
import { pipe, andThen as then, prop, otherwise, always } from 'ramda'
import getBook from '/src/api/getBook'
let title = ref('')
let price = ref('')
let onClick = pipe(
always(1),
getBook,
then(prop('data')),
then(effect('title', title)),
then(effect('price', price)),
otherwise(console.error)
)
</script>
19 行
let onClick = pipe(
always(1),
getBook,
then(prop('data')),
then(effect('title', title)),
then(effect('price', price)),
otherwise(console.error)
)
使用 pipe()
組合 onClick()
:
always(1)
:準備getBook
的參數getBook
:傳入getBook()
thunkify()
結果不變,但使用 thunkify()
改寫。
<template>
<div>
<button @click="onClick">Get Book</button>
</div>
<div>
{{ title }} / {{ price }}
</div>
</template>
<script setup>
import { ref } from 'vue'
import { effect } from 'vue3-fp'
import { pipe, andThen as then, prop, otherwise, thunkify } from 'ramda'
import getBook from '/src/api/getBook'
let title = ref('')
let price = ref('')
let onClick = pipe(
thunkify(getBook)(1),
then(prop('data')),
then(effect('title', title)),
then(effect('price', price)),
otherwise(console.error)
)
</script>
19 行
let onClick = pipe(
thunkify(getBook)(1),
then(prop('data')),
then(effect('title', title)),
then(effect('price', price)),
otherwise(console.error)
)
使用 pipe()
組合 onClick()
:
thunkify(getBook)(1)
:將fetchBook()
轉成 Thunk,也就是() -> a
的 function,如此則符合pipe()
要求
Conclusion
always()
與thunkify()
皆能產生() -> a
,只是always()
從 data 下手,而thunkify()
是從 function 下手thunkify()
在 Vue 3 使用有時會喪失 reactivity,如watch()
,使用always()
則正常