實務上難免會出現 Runtime Exception,此時可使用 Ramda 的 tryCatch()
產生新的 Function。
Version
macOS Catalina 10.15.3
VS Code 1.43.0
Quokka 1.0.277
Ramda 0.27.0
Imperative
Object Literal
let data = {
title: 'FP in JavaScript',
price: 100
}
let f = obj => obj.title.toUpperCase()
f(data) // ?
f()
想從 object 取得 title
property 並轉成大寫。
Null
let data = {
title: 'FP in JavaScript',
price: 100
}
let f = obj => obj.title.toUpperCase()
f(null) // ?
若傳入 null
,由於沒有 title
property,因此出現 runtime exception。
Try Catch
let data = {
title: 'FP in JavaScript',
price: 100
}
let f = obj => {
try {
return obj.title.toUpperCase()
} catch {
return 'N/A'
}
}
f(data) // ?
f(null) // ?
使用 try catch
攔截,若出現 exception 就顯示 N/A
。
Ramda
prop()
import { prop, toUpper, pipe } from 'ramda'
let data = {
title: 'FP in JavaScript',
price: 100
}
let f = pipe(
prop('title'),
toUpper
)
f(data) // ?
Ramda 會使用 pipe()
將 prop()
與 toUpper()
組合,這對正常 object 不是問題。
Null
import { prop, toUpper, pipe } from 'ramda'
let data = {
title: 'FP in JavaScript',
price: 100
}
let f = pipe(
prop('title'),
toUpper
)
f(null) // ?
若傳入 null,f()
就爆了。
不過 prop('title')
與 obj.title
情況又不一樣。
prop('title')
若取不到 property 會回傳 undefined
,使的 toUpper()
產生 exception,但 obj.title
是直接產生 exception。
tryCatch()
import { prop, toUpper, pipe, tryCatch, always } from 'ramda'
let data = {
title: 'FP in JavaScript',
price: 100
}
let f = pipe(
prop('title'),
tryCatch(toUpper, always('N/A'))
)
f(data) // ?
f(null) // ?
也因為 exception 只出現在 toUpper()
,因此將 tryCatch()
用在 toUpper()
即可。
toCatch()
(…x → a) → ((e, …x) → a) → (…x → a)
若第一個 function 產生 exception,則回傳第二個 function,否則回傳第一個 function
Conclusion
- 傳統
try catch
是 imperative 用在處理 variable,而tryCatch()
是用在處理 function,若有 exception 則回傳另一個 function,適合 function composition
Reference
Ramda, tryCatch()
Ramda, prop()
Ramda, toUpper()
Ramda, pipe()
Ramda, always()