楔子
寫程式時噴錯誤是蠻常見的,就每發生一個錯誤,再加一個條件去排除錯誤的問題
往往如此, code 就會開始蠻的有點「巢狀」的感覺
if(check) {
// 1-level
if(check) {
// 2-level
if(check) {
// 3-level
} else {
// 3-level
}
} else {
// 2-level
}
} else {
// 1-level
}
原來的 try-catch
標準的 try-catch 程式長相大概如下, try-catch 主要的功用就是避免程式噴錯跳離
try {
// do something
} catch (e) {
console.log(e.message)
}
但也常常有個問題就是錯誤的類型如果不確定,就常常一直補 code 除錯。
所以常常的流程大概就是
包一個 try-catch ,噴錯看 log ,補 if-else 的 bug handling,再重覆 try-catch 的 log..
// version 1
function go(x) {
try {
let len = x.length
return [...len, 1]
} catch (e) {
console.log(e.message)
}
}
// version 2
function go1(x) {
try {
if (x !== undefined) {
let len = x.length
return [...len, 1]
}
} catch (e) {
console.log(e.message)
}
}
go(undefined) // 噴 undefined 沒有 length
go(['hello'])
那是不是有方式可以反正噴就直接先給 null (駝鳥心態..嘿嘿..)
這種情況蠻常發生的,就是當取得的資料是從外部或資料庫來的,
有時存的東西和想像的不太一致(應該說東西愈來愈多總會有些不受控的情況)
有沒有先可以把流程跑完再回來慢慢解..
另一種的 tryCatch
這是換一個角度想,就我們用一個 function 然後執行它,
如果有任何的噴錯,接下來進行所有的動作都「忽略不處理」,
沒錯誤就一直走下去,到時看結果有些不太合理的結果再回來檢查數據來源,
至少程式處理端是沒有問題的,也比較好了解真正的錯誤原因(數據方面)
來試試看吧
先運用之前提的 Box 的觀念,把值塞在裡面..
function tryCatch(f) {
try {
return Right(f())
} catch (e) {
return Left(e)
}
}
let go1 = tryCatch(() => undefined.length).map(x => x + 1) // Left(e)
let go2 = tryCatch(() => 2).map(x => x + 1) // Right(2)
參考 code
const Box = x =>
({
map: f => Box(f(x)),
inspect: () => `Box(${x})`
})
const Right = x =>
({
map : f => Right(f(x)),
inspect : () => `Right(${x})`
})
const Left = x =>
({
map : f => Left(x),
inspect : () => `Left(${x})`
})