JavaScript-處理錯誤的方法

一步一步弄懂它。

簡述

會寫這篇是因為對 JS 的錯誤處理不是很熟,而最近正好碰到了一個不錯的範例,想藉此來解釋一下錯誤處理的流程,跟順便介紹 throw Error 的用法。

範例

錯誤處理應該最發生在常串接 API 的時候,所以這邊就用 API 來當範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function App () {
const [data, setData] = useState(null)
const [isPending, setIsPending] = useState(false)
const [error, setError] = useState(null)

useEffect(() => {
const fetchData = async () => {
setIsPending(true)
try {
const response = await fetch(...)
if (!response.ok) throw new Error(response.statusText)
const json = await response.json()
setData(json)
} catch (err) {
console.log(err.message)
setError('Can not fetch the data')
} finally {
setIsPending(false)
}
}
fetchData()
}, [])

return ...
}

首先先介紹一下 try...catch...finally 的用途。

try 裡面負責處理「我們預期執行的 code」,一旦這裡面拋出了「Exception(例外情形)」,就會立刻進到 catch 區塊,所以 catch 中會放我們想要「處理例外情形的 code」。

最後是 finally,這個是不論有沒有出現例外情形,最後都會執行到的區塊,所以可以在這邊放「執行正確或錯誤都要執行的東西」。

以上面的例子來說,我們首先用 try 包住了 fetch API 的程式碼,所以如果正確執行的話就會:

  1. 取得 API 資料
  2. 把資料寫入 state

你可能會想說 if (!response.ok) throw new Error(response.statusText) 的用意何在?

它的任務可重要了,這是因為對 fetch 而言,只要 request 發的出去都不算是 Exception(很重要的觀念),所以 404 或 500 這些都不算數,既然不算數,就不會進到 catch 區塊,這樣子麻煩可就大了。

因此這些拿不到資料的情況我們必須自己處理,透過「人工拋出 Exception」的方式來達成,否則的話是不會進入 catch 區塊的哦!

至於 finally 的部分很簡單,因為不論最後 fetch 成功還是失敗都要停止 loading(isPending)的狀態,所以把 setIsPending 放在這邊來處理會是不錯的選擇。

關於 Error 物件

這個物件最主要會包含兩個東西:

  • name
  • message

name 是用來說明這是什麼型別的例外,常見的有:

  • Error 通用的錯誤(通常用在客製化)
  • RangeError(數字超出範圍)
  • ReferenceError(找不到變數)
  • SyntaxError(語法錯誤)
  • TypeError(找不到函式)
  • URIError(當用了內建的 URI Method 卻給了不合法的 URI 格式)
  • EvalError(不正確的使用 Eval 這個函式)

所以我們透過 throw 來拋出錯誤時,就是在指定這 name 跟 message 這兩個東西。像 throw new Error(response.statusText) 的意思就是拋出一個:

  • name = Error(種類)
  • message = response.statusText(內容)

的例外情形。

這邊看完後再回去看上面的例子應該就會理解許多了,希望之後對於錯誤處理能夠越來越掌握。

參考資源

關於 Catch Error 的實際案例 React 的第九個 hook:useReducer
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×