iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 12
1

此篇文章將說明如何透過 Sources 面板建立斷點來暫停 JavaScript 的執行,除了手動標記行號以外,還有非常多種方式,適用不同的情境。

注意重整頁面不會影響以建立的斷點,這也是斷點的一大核心機制

概覽

最常見的斷點建立方式就是標記特定一行程式碼,但面對各種不同 Debug 情境,尤其是程式碼非常多時,可能無法一下就找到精確的檔案或位置,此時直接標記的方式就顯得沒有效率。

本篇文章中筆者將會介紹 Sources 面板的右側子面板中關於各種斷點的建立方式以及使用時機,斷點主要有分為:

  • 標記 – 執行到程式碼特定位置
  • 條件標記 – 同上,但只有在條件成立時才中斷
  • DOM – 特定 DOM 元素發生變化
  • 請求 – 請求的網址符合條件
  • Event listener – 特定事件觸發
  • Exception – 錯誤產生
  • Function – 特定 Function 執行

閱讀本文時,建議搭配 Demo 頁面 Sources - Breakpoints,效果更佳。

標記

標記斷點的官方名稱為 line-of-code,可以在該行程式碼執行前暫停,不過 Chrome DevTools 經歷多次改版,已經可以做到特定位置的標記,讓標記的位置更加彈性,例如在同一行用到 forEachmap 等等遍歷 Function 時可以直接跳過。

標記的方式非常簡單,可以在 Demo 頁面中嘗試:

  1. 開啟 Sources 面板
  2. 打開想要中斷的檔案
  3. 點擊程式碼的行號建立斷點

別忘了試試特定位置的標記功能,點擊行號後可以看到右方的出現了多個小箭頭,在右側的斷點選單中透過右鍵選項跳到斷點建立的位置。

除了一般的標記外,右鍵點擊行號可以看到其他標記

  • Add conditional breakpoint – 可以加入條件,執行結果不如預期時才中斷
  • Add logpoint – 如同插入一個 console.log
  • Never pause here – 可用來跳過 debugger

logpoint

雖然看起來和 console.log 沒什麼兩樣,但加入 logpoint 後可以快速開關且修改程式碼,重整頁面時會保留,重要的是當程式碼來源是 source map 時,因為實際上執行的並不是這份程式碼,修改內容並不會有效果,此時就可以利用 logpoint 來插入想要執行的程式碼。

 

debugger

除了在程式碼中加入標記,在實際的程式碼中放入 debugger 也會暫停程式碼執行,效果和加入斷點標記相同,比起插入一堆 console.log,利用 debugger 能夠獲得更多資訊,更容易解決問題。

console.log(1);
console.log('pause');
debugger;
console.log(2);

 

DOM

在某個 DOM 元素被修改時暫停程式碼執行,Inspect 一個元素時可以在右鍵選單的 Break on 中看到三種斷點:

  • Subtree modifications – 該節點的發生變化,如子節點的新增或刪除
  • Attribute modifications – 節點本身的 attribute 有新增、刪除、修改
  • Node removal – 該節點被移除,同時 DOM 斷點也會消失。

當某個節點在事件和 JavaScript 的作用下很難直接觀察變化時就可以使用 DOM 斷點,例如某個元素一直變化,但不知道是哪個 Function 在修改它:

找到了隨機修改顏色的 setInterval

 

請求

在 Sources 面板右側選單的 XHR/Fetch Breapoints 可以新增 URL 或是攔截所有請求,好用的地方在於開發時常會被各種請求淹沒,測試 API 的過程透過請求斷點能快速找到發出請求的程式碼,也能避免後續的請求影響 Log 的觀察。

 

Event listener

展開最下面的 Event Listener Breakpoints 後會有各種事件類別,可以勾選類別監聽同類的所有事件或是監聽單一事件,注意 Event listener 斷點的暫停時機是在觸發事件後、Listener 執行前,而這也是筆者認為最好用的斷點。

網頁中許多行為都靠事件觸發,透過 Event listener 斷點能快速找到行為對應的程式碼位置,另外也能在調整樣式時做到 JavsScript 版的狀態鎖定。

舉個實際的例子,調整某個元素的 CSS 時,如果元素的 Hover 行為是由 JavaScript 的 mouseentermouseleave 控制,就無法靠 Elements 面板中的狀態鎖定讓元素保持「Hover」狀態,又或是想要調整某個 Dialog 的 CSS 卻因為點擊 DevTools 觸發 Blur 事件把 Dialog 關閉,尤其元素是來自第三方套件時又更加麻煩。

怎麼樣都 Inspect 不到,氣死

  1. 首先勾選 Mouse > mousedown
  2. 展開選單後,點擊選項觸發註冊的 mouseenter lisenter
  3. 順利阻止選單消失,停在 mousedown Event handler 的第一行

如此一來就能順利調整 CSS 並看到變化了!這個問題曾經讓筆者非常頭痛呢。
 

Exception

點擊右上方的八邊形暫停標誌可以在出現錯誤時暫停,預設只有未攔截的錯誤會暫停,需要另外勾選 Pause on caught exceptions 才會讓 try catch 中的錯誤也觸發暫停

注意 Promise 的 reject 即使有 catch 還是會觸發斷點。

開啟 Exception 斷點測試網頁功能時就能在錯誤出現的當下置身犯罪現場,檢查是否有不預期的錯誤發生。

 

Function

在 Console 面板中可以用 debug 相當於在該 function 的第一行插入 debugger,直接看程式碼:

function a(){
  console.log(1);
}
// in the Console
debug(a)

上下的效果是一模一樣的

function a() {
  debugger;
  console.log(1);
}

不過 debug 建立的斷點不會出現在 Sources 面板中,只能使用 undebug 解除,另外關於更多 Console 的 Utilities function 可以參考 Console - Utilities

小結

今天介紹了各種斷點的使用方式,只要應用得當幾乎能涵蓋所有情境,不過除了事先建立斷點外,別忘了還有手動暫停,只要按下 F8 就會立即暫停 JavaScript 執行。

明天的文章將會介紹暫停後該如何逐步執行 JavaScript。


上一篇
[Day 11] Sources - Workspace
下一篇
[Day 13] Sources - Step-by-Step Execution
系列文
你所不知道的各種前端 Debug 技巧30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言