針對 User 輸入做 Validation 時,若有任何錯誤則不再繼續執行,這種 Control Flow 正適合 Either。
Version
Vue 3.0.11
Sanctuary 3.1.0
Composition API
當輸入為空白時,按下 Submit
會顯示 name is empty
。
當輸入 Sam
時,按下 Submit
將顯示 Hello Sam
。
<template lang='pug'>
div
input(v-model='name')
button(@click='onClick') Submit
div {{ msg }}
</template>
<script setup>
ref: name = ''
ref: msg = ''
let onClick = () => {
if (name === '') msg = 'name is empty'
else msg = `Hello ${name}`
}
</script>
12 行
let onClick = () => {
if (name === '') msg = 'name is empty'
else msg = `Hello ${name}`
}
Imperative 會使用 if else
判斷,將顯示結果直接寫入 msg
state。
Either
結果不變,但使用 Either 改寫。
<template lang='pug'>
div
input(v-model='name')
button(@click='onClick') Submit
div {{ msg }}
</template>
<script setup>
import { ref } from 'vue'
import { read, write } from 'vue3-fp'
import { pipe, isEmpty, ifElse, thunkify, concat, map } from 'ramda'
import { Left, Right, either, I } from 'sanctuary'
let name = ref('')
let msg = ref('')
let chkEmpty = ifElse(
isEmpty,
thunkify(Left)('name is empty'),
Right
)
let onClick = pipe(
read(name),
chkEmpty,
map(concat('Hello ')),
either(I)(I),
write(msg)
)
</script>
23 行
let onClick = pipe(
read(name),
chkEmpty,
map(concat('Hello ')),
either(I)(I),
write(msg)
)
使用 pipe()
組合出 onClick()
:
read(name)
:讀出name
statechkEmpty
:檢查輸入是否為空白,並回傳 Eithermap(concat('Hello '))
:因為chkEmpty()
回傳 Either,若要對name
state 作處理,必須將 function 包在map()
才能修改 Either 內部值either(I)(I)
:從 Either 內部讀出值write(msg)
:寫入name
state
17 行
let chkEmpty = ifElse(
isEmpty,
thunkify(Left)('name is empty'),
Right
)
使用 ifElse()
組合出 chkEmpty()
:
isEmpty
:檢查輸入是否為空白thunkify(Left)('name is empty')
:若輸入為空白,則回傳 Left Either,相當於 ExceptionRight
:正常值則回傳 Right Either
Conclusion
- 關鍵在於 Either 之後的值若需處理,必須統一放在
map()
內,類似 Promise 需在then()
內處理,且只要是 Left Either,則map()
內的 function 都不會執行,類似 Imperative 的 Exception