SlideShare a Scribd company logo
1 of 52
7. 錯誤處理
• 學習目標
– 認識throw使用時機
– 使用try-catch處理
錯誤
– 處理Promise錯誤
– 結合await、await與
try-catch
2
3
4
5
6
• 在設計函式或方法時,遇到無法繼續流程
的錯誤時,想令呼叫者有機會處理錯誤,
才是拋出錯誤的目的
7
• 如果在函式中,程式碼流程先return了,
finally區塊會先執行完後,再將值傳回
8
掌握錯誤型態
• SyntaxError
• ReferenceError
• TypeError
• RangeError
• URIError
9
SyntaxError
• 剖析程式碼語法時期
• eval()、JSON.parse()剖析失敗
10
• 試圖使用未宣告的名稱
11
ReferenceError
TypeError
• 試圖操作物件上不存在的行為
12
RangeError、URIError
• 在呼叫某些API時,指定的引數有誤時會拋
出的錯誤
– Number.toExponential()、
Number.toFixed()或
Number.toPrecision()若引數有誤會拋出
RangeError
– encodeURI()或decodeURI()有誤會拋出
URIError。
13
• try-catch並不支援多個catch區塊
14
• ES10以後catch可以不寫括號部份
15
自訂錯誤型態
• JavaScript最初是為瀏覽器而生,可用資源
相對有限,錯誤的類型也就相對地少
• ECMAScript多數規範是集中在語言本身,
標準錯誤型態多半也是跟語言本身相關
• 不同環境或其他技術標準的錯誤類型,是
由各個環境自行實作,或是其他技術標準
來規範
16
• 對於應用程式或程式庫開發,建議針對需
求,發展自己的一套錯誤型態,令錯誤處
理能突顯應用程式或程式庫的意圖
17
18
19
20
• 程式邏輯錯誤,也就是程式寫錯了,若發
現了這類錯誤,應該停止程式執行並修正
程式碼,而不是捕捉錯誤時粉飾太平
• 視需求而定,若捕捉錯誤後,當時情境沒
有足夠的資訊可以妥善處理,可就現有資
訊處理完錯誤後,重新拋出原錯誤,或者
是收集資訊後建立新的錯誤拋出
21
堆疊追蹤(Stack Trace)
22
23
• 要善用堆疊追蹤,前題是程式碼中不可有
私吞錯誤的行為
• 這樣的程式碼會對應用程式維護造成嚴重
傷害
24
• 在使用throw再度拋出同一錯誤實例時,
錯誤的追蹤堆疊起點,仍是錯誤的發生根
源,而不是重拋錯誤的地方
25
26
• 如果捕捉錯誤後,拋出了新的錯誤實例,
堆疊追蹤就會中斷
27
28
產生器與錯誤處理
• throw()方法可以指定Error實例,在產
生器函式中拋出例外
• 在拋出例外之後,呼叫產生器的next()方
法不會再有進一步結果
29
30
• 如果產生器函式定義流程時,包含了try-
catch語法,而且流程已進入try區塊,呼
叫throw()時指定的Error實例,就可以
被捕捉
31
• 流程必須已進入try區塊,錯誤才會被捕捉
• 上面的範例如果沒呼叫過g.next(),就直
接g.throw()的話,主控台會顯示以下的
訊息
32
• 在實作Symbol.iterator時,選擇性地
實作return()與throw()方法
33
34
回呼模式錯誤處理
• 在呼叫了非同步函式之後,流程就會離開
了try區塊
• 若非同步的任務執行過程中發生錯誤,已
不是呼叫非同步函式時對應的catch區塊
可處理
35
36
• 如果實作非同步任務時採取回呼模式,想
在任務無法執行時處理錯誤,是將Error
實例當成引數傳入回呼函式
37
38
39
• 若錯誤真的發生,而程式碼中沒有檢查,
那麼錯誤就會靜悄悄地被忽略了
• 這就好比寫了catch區塊卻內容空白一樣,
對查找臭蟲時是很大的麻煩
• 為了避免被忽略,通常錯誤實例會作為回
呼函式的第一個引數,算是對開發者的基
本提醒:「別忘了檢查錯誤」
40
Promise與錯誤處理
• Promise被否決時,表示任務因為某個錯
誤而無法執行下去
• 使用reject否決任務,可以對比為同步流
程時throw錯誤的概念
41
• 如果Promise在執行任務時拋出了錯誤,
會隱含地以指定的錯誤物件作為reject的
引數來否決任務
• 在不同的環境中會有不同的呈現方式
– Node.js:
UnhandledPromiseRejectionWarning
– 瀏覽器:Uncaught (in promise)
42
• 如果then()指定的回呼函式中拋出了錯誤,
就是否決then()傳回的Promise
43
• 如果錯誤沒在then()中處理掉,then()
傳回的Promise也會被否決
• 在形成鏈狀呼叫時,就會類似throw錯誤
時中斷流程的概念
44
• then()或catch()是各自獨立的
• 也就是各自傳回Promise,如果then()或
catch()沒有拋出錯誤,傳回的Promise
任務就算達成
45
46
• 對於catch()應該理解為,只要沒有再度
拋出錯誤,捕捉錯誤的任務就達成了
• ES9提供了finally()方法,這就可以形
成類似try-catch-finally的風格
47
async、await與錯誤處理
• 在async函式throw錯誤,表示任務無法
達成,相當於呼叫Promise的reject時指
定了錯誤物件
48
• 在使用await的情況下,結合try-catch
錯誤處理語法上就成了可能
49
非同步產生器與錯誤處理
• 非同步產生器具有throw()方法,呼叫時
傳入錯誤物件,可以在非同步產生器函式
定義的流程中拋出錯誤
• 如果非同步產生器函式中定義了try-
catch,而且流程已經在try區塊中,那麼
錯誤就可以被catch捕捉處理
50
51
• 如果非同步產生器函式中沒有處理錯誤的
話,由於本質上也是個async函式,拋出
錯誤相當於否決任務,必須在throw()方
法傳回的Promise中進行處理
52

More Related Content

What's hot

What's hot (20)

Java SE 7 技術手冊投影片第 08 章 - 例外處理
Java SE 7 技術手冊投影片第 08 章 - 例外處理Java SE 7 技術手冊投影片第 08 章 - 例外處理
Java SE 7 技術手冊投影片第 08 章 - 例外處理
 
11, exceptions
11, exceptions11, exceptions
11, exceptions
 
並行與平行
並行與平行並行與平行
並行與平行
 
CH10:輸入輸出
CH10:輸入輸出CH10:輸入輸出
CH10:輸入輸出
 
流程語法與函式
流程語法與函式流程語法與函式
流程語法與函式
 
Java SE 8 技術手冊第 11 章 - 執行緒與並行API
Java SE 8 技術手冊第 11 章 - 執行緒與並行APIJava SE 8 技術手冊第 11 章 - 執行緒與並行API
Java SE 8 技術手冊第 11 章 - 執行緒與並行API
 
9. meta-programming
9. meta-programming9. meta-programming
9. meta-programming
 
Java Tutorial:Learn Java in 06:00:00
Java Tutorial:Learn Java in 06:00:00Java Tutorial:Learn Java in 06:00:00
Java Tutorial:Learn Java in 06:00:00
 
Java SE 8 技術手冊第 5 章 - 物件封裝
Java SE 8 技術手冊第 5 章 - 物件封裝Java SE 8 技術手冊第 5 章 - 物件封裝
Java SE 8 技術手冊第 5 章 - 物件封裝
 
輸入輸出
輸入輸出輸入輸出
輸入輸出
 
執行緒與並行API
執行緒與並行API執行緒與並行API
執行緒與並行API
 
6. 非同步設計
6. 非同步設計6. 非同步設計
6. 非同步設計
 
5, initialization & cleanup
5, initialization & cleanup5, initialization & cleanup
5, initialization & cleanup
 
2. 從 REPL 到 IDE
2. 從 REPL 到 IDE2. 從 REPL 到 IDE
2. 從 REPL 到 IDE
 
RSpec & TDD Tutorial
RSpec & TDD TutorialRSpec & TDD Tutorial
RSpec & TDD Tutorial
 
CH14:NIO 與 NIO2
CH14:NIO 與 NIO2CH14:NIO 與 NIO2
CH14:NIO 與 NIO2
 
Java SE 8 技術手冊第 2 章 - 從JDK到IDE
Java SE 8 技術手冊第 2 章 - 從JDK到IDEJava SE 8 技術手冊第 2 章 - 從JDK到IDE
Java SE 8 技術手冊第 2 章 - 從JDK到IDE
 
並行、平行與非同步
並行、平行與非同步並行、平行與非同步
並行、平行與非同步
 
Nashorn on JDK 8 (ADC2013)
Nashorn on JDK 8 (ADC2013)Nashorn on JDK 8 (ADC2013)
Nashorn on JDK 8 (ADC2013)
 
为啥别读HotSpot VM的源码(2012-03-03)
为啥别读HotSpot VM的源码(2012-03-03)为啥别读HotSpot VM的源码(2012-03-03)
为啥别读HotSpot VM的源码(2012-03-03)
 

More from Justin Lin

More from Justin Lin (20)

Ch14 簡介 Spring Boot
Ch14 簡介 Spring BootCh14 簡介 Spring Boot
Ch14 簡介 Spring Boot
 
Ch13 整合 Spring MVC/Security
Ch13 整合 Spring MVC/SecurityCh13 整合 Spring MVC/Security
Ch13 整合 Spring MVC/Security
 
Ch12 Spring 起步走
Ch12 Spring 起步走Ch12 Spring 起步走
Ch12 Spring 起步走
 
Ch11 簡介 JavaMail
Ch11 簡介 JavaMailCh11 簡介 JavaMail
Ch11 簡介 JavaMail
 
Ch10 Web 容器安全管理
Ch10 Web 容器安全管理Ch10 Web 容器安全管理
Ch10 Web 容器安全管理
 
Ch09 整合資料庫
Ch09 整合資料庫Ch09 整合資料庫
Ch09 整合資料庫
 
Ch08 自訂標籤
Ch08 自訂標籤Ch08 自訂標籤
Ch08 自訂標籤
 
Ch07 使用 JSTL
Ch07 使用 JSTLCh07 使用 JSTL
Ch07 使用 JSTL
 
Ch06 使用 JSP
Ch06 使用 JSPCh06 使用 JSP
Ch06 使用 JSP
 
Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器
 
Ch04 會話管理
Ch04 會話管理Ch04 會話管理
Ch04 會話管理
 
Ch03 請求與回應
Ch03 請求與回應Ch03 請求與回應
Ch03 請求與回應
 
Ch02 撰寫與設定 Servlet
Ch02 撰寫與設定 ServletCh02 撰寫與設定 Servlet
Ch02 撰寫與設定 Servlet
 
CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式
 
14. 進階主題
14. 進階主題14. 進階主題
14. 進階主題
 
13.並行、平行與非同步
13.並行、平行與非同步13.並行、平行與非同步
13.並行、平行與非同步
 
12. 除錯、測試與效能
12. 除錯、測試與效能12. 除錯、測試與效能
12. 除錯、測試與效能
 
11. 常用內建模組
11. 常用內建模組11. 常用內建模組
11. 常用內建模組
 
10. 資料永續與交換
10. 資料永續與交換10. 資料永續與交換
10. 資料永續與交換
 
9. 資料結構
9. 資料結構9. 資料結構
9. 資料結構
 

7. 錯誤處理