try-catch.js
js
const safeChain = (state, mapper) => {
try {
return mapper(state)
} catch (e) {
return undefined
}
}
module.exports = {safeChain}
safe-chain
core
js
const symbol = Symbol('safe')
const isNullish = value => value === undefined || value === null
const isPack = pack => typeof pack === 'object' && symbol in pack
const pack = value => ({ [symbol]: value })
const unpack = pack => pack[symbol]
const toProxy = (state, revokes) => {
const wrap = pack(state)
const handler = trap(revokes)
const {proxy, revoke} = Proxy.revocable(wrap, handler)
revokes.push(revoke)
return proxy
}
const trap = (revokes) => {
return {
get (target, key) {
const unpacked = unpack(target)
return key === symbol ?
unpacked :
toProxy(isNullish(unpacked) ? undefined : unpacked[key], revokes)
}
}
}
module.exports = {toProxy, isPack, unpack}
index
js
const {toProxy, isPack, unpack} = require('./core')
const safeChain = (state, mapper) => {
const revokes = []
const proxy = toProxy(state, revokes)
const mappedResult = mapper(proxy)
const result = isPack(mappedResult) ? unpack(mappedResult) : mappedResult
revokes.forEach(fn => fn())
return result
}
module.exports = {safeChain}
example
js
const {safeChain} = require('./index')
const backendApi = {
fetchResponse() {
this.response = {
result: { message: 'Success' },
status: 200,
statusCode: 'Ok'
}
},
response: null,
get result () {
return safeChain(this.response, ({result}) => result)
}
}
console.log(backendApi.result) // undefined
backendApi.fetchResponse()
console.log(backendApi.result) // { message: 'Success' }