欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript必備的斷點調(diào)試技巧總結(jié)(推薦)

 更新時間:2021年09月06日 10:20:31   作者:大轉(zhuǎn)轉(zhuǎn)FE  
打斷點操作很簡單,核心的問題在于,斷點怎么打才能夠排查出代碼的問題所在呢?下面這篇文章主要給大家總結(jié)介紹了關(guān)于JavaScript必備的斷點調(diào)試技巧,需要的朋友可以參考下

為什么要使用 debugger

這篇文章將介紹如何使用斷點來進行 JavaScript 調(diào)試。在讀這篇文章之前,需要問一個問題:為什么要使用斷點來進行調(diào)試?
我們需要了解使用斷點的必要性,否則下文介紹的所有斷點調(diào)試方法都會是廢話。console.log 是前端開發(fā)最常用的調(diào)試手段,它簡單直接解決一部分問題。但當遇到十分復(fù)雜的問題,console.log 就會變得不趁手。比如:

  • 一個邏輯復(fù)雜的算法
    如果你刷過 leetcode 一定深有體會,算法某個測試用例報錯了,有時很難光靠目測找出有問題的那個方法。
  • 一個復(fù)現(xiàn)步驟十分繁瑣的bug。
    花了10分鐘好不容易復(fù)現(xiàn)了,但是只跟蹤到某行代碼,需要第二次添加 log 才能繼續(xù)尋找問題。查看log -> 添加log -> 查看log... 這個過程重復(fù)幾遍,今天剩下的磚就搬不完了。
  • 一段運行流程冗長的代碼
  • 一段沒有注釋、起名隨意的代碼
  • server 端代碼
    有 nodejs 服務(wù)端開發(fā)經(jīng)驗的同學(xué)相信有過 postman <-> ide 反復(fù)橫跳的經(jīng)歷,如果光靠 log,對于一個巨大的復(fù)雜對象,控制臺是不好查看全貌的。如果一個接口還涉及到數(shù)據(jù)庫增刪、第三方依賴,那么復(fù)原上一次請求造成的后果也是一件痛苦的事情。

在這些情況下,斷點調(diào)試是非常有價值的,將 debug 的時間復(fù)雜度從 O(n) 降到 O(1),讓搬磚更快樂。

這是文章的內(nèi)容大綱:

  • Chrome debugger 基本用法
  • VS Code 調(diào)試 SPA 應(yīng)用
  • Chrome 調(diào)試 Nodejs
  • VS Code 調(diào)試 Nodejs

Chrome debugger 基本用法

最簡單的斷點調(diào)試,就是在代碼中加一句 debugger,然后到瀏覽器中刷新頁面,這時候瀏覽器就會在 debugger 語句那停止執(zhí)行。

為了方便理解,引入一個簡單例子,在一個文件夾中創(chuàng)建 index.html 和 index.js,然后在 index.html 中引入 index.js。index.js 內(nèi)容如下:

// 國際慣例,hello world。
const greet = () => {
  const greeting = "hello debugger";
  // 瀏覽器執(zhí)行到這里將會暫停
  debugger
  console.log(greeting);
};

greet();

console.log("js evaluation done");

執(zhí)行命令:

npm i -g serve
serve .

然后訪問 http://localhost:5000并打開開發(fā)者工具。

這時候我們的 hello world 斷點就打上了,就像這樣:

圖中分為四個區(qū)域,藍色區(qū)域用于文件選擇,Page 一欄是指當前頁面中的 JS 文件,F(xiàn)ilesystem 會顯示我們系統(tǒng)中的文件。通常我們使用 Page。

粉色是代碼的行號和內(nèi)容。代碼的行號處可以通過點擊來添加新的斷點,再次點擊后取消。

黃色區(qū)域用于控制代碼的執(zhí)行,只需要掌握前四個按鈕的含義,就可以應(yīng)付絕大多數(shù)場景。按鈕1是讓代碼繼續(xù)執(zhí)行(resume),如果遇到下一個斷點就會再次中斷執(zhí)行。按鈕2可以讓瀏覽器執(zhí)行當前行(圖中是第3行),然后在下一行中斷代碼,按鈕3是進入當前函數(shù),查看函數(shù)具體內(nèi)容。假設(shè)我們當前停在第7行 greet() ,點擊按鈕3就會進入 greet 方法中(也就是第2行)。如果不想再看 greet 方法了,就點擊按鈕4,跳出這個方法,回到第8行。

綠色區(qū)域可以查看變量的內(nèi)容和當前的調(diào)用棧。

debugger 是最簡單粗暴的打斷點方式,但是需要修改我們的代碼。需要注意的是,上線前必須刪除這些語句。也可以通過配置 webpack 來自動去除。不過終究還是有些不方便,所以我們來看下如何通過 vscode 來簡化打斷點的方式。

VS Code 調(diào)試 SPA 應(yīng)用

首先我們使用 Vite 來創(chuàng)建一個 Vue 應(yīng)用用于演示(React步驟類似)。

# 創(chuàng)建 vut-ts 應(yīng)用
npm init vite
cd hello-vite
npm install
# 調(diào)用 VS Code cli 打開項目,或者手動在 VS Code 打開。
code .
npm run dev

然后在 VS Code 中新建一個文件 .vscode/launch.json,填入這些內(nèi)容:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "pwa-chrome",
      "request": "launch",
      "name": "Launch Vue project",
      // 這里填入項目的訪問地址
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}"
    },
  ]
}

然后使用 cmd+q 退出你正在運行的 Chrome(這步很重要,不能跳過),按 f5 啟動 VS Code 的調(diào)試功能。VS Code 就會幫你啟動一個 Chrome 窗口,并訪問上述配置的中的 url。這時候我們的斷點就生效了,可以一步一步地控制代碼的運行,找出 bug 來源。

這里有一個實用的小技巧,就是在 BREAKPOINTS 中,把 Uncaught Exceptions 勾上,這樣在代碼報錯的地方,就會自動中斷執(zhí)行。當我們遇到一個報錯時,采用這個方法可以省去定位問題代碼的時間。

另外我們可以發(fā)現(xiàn),在 VS Code 斷點生效時,Chrome Devtools 也會同步這個展示這個斷點。

在 VS Code 中,調(diào)試有兩種模式,分別是 launch 和 attach。由于真正執(zhí)行代碼的是 Chrome 中的 JS 引擎,所以是否中斷代碼的控制權(quán)是在 Chrome 手里的。那為什么 VS Code 的斷點可以控制代碼的中斷呢?是因為 VS Code 通過 devtools-protocol 向 Chrome 發(fā)起指令,告訴 Chrome 需要在哪一行代碼暫停執(zhí)行。這個發(fā)送指令的過程,被稱作 attach。 而 launch 的過程包含 attach ,即先 launch(啟動) 瀏覽器,然后 attach(附加) 斷點信息。所以 attach 模式是 launch 模式的子集。

聽起來好像 launch 模式會更方便,為我們省去了手動啟動瀏覽器的過程。但是這存在一個問題,如果同時開發(fā)多個前端工程會怎樣?每個工程啟動一個調(diào)試進程,就會打開多個瀏覽器,那么在多個瀏覽器之間切換就會顯得很麻煩。我們可以使用 attach 模式解決這個問題。

首先我們使用命令行啟動 Chrome。使用命令行的原因是,我們需要給 Chrome 的啟動傳參。

# 運行這條命令前需要cmd+q退出已運行的Chrome
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
# 如果看到這個輸出,說明傳參成功。
DevTools listening on ws://127.0.0.1:9222/devtools/browser/856a3533-ca5c-474f-a0cf-88b7ae94c75b

VS Code 和 Chrome 是通過 websocket 交流,--remote-debugging-port 指定了 websocket 使用的端口。然后我們將 launch.json 文件修改成這樣:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "pwa-chrome",
      "request": "attach",
      "name": "Vue Application",
      // 項目訪問的 url
      "url": "http://localhost:3000",
      // websocket 端口,需要與 --remote-debugging-port 參數(shù)保持一致。
      "port": 9222,
      "webRoot": "${workspaceFolder}"
    },
  ]
}

注意在啟動 VS Code 調(diào)試之前,需要在 Chrome 中打開 http://localhost:3000 這個頁面。然后我們在 VS Code 中打上斷點,刷新瀏覽器,代碼就成功停在斷點處了。第二個、第n個工程都可以采用相同的配置,區(qū)別是 url 字段要根據(jù)項目配置進行修改。

Chrome 調(diào)試 Nodejs

上文講的是如何調(diào)試頁面,接下來我們聊如何調(diào)試 nodejs 應(yīng)用。首先來一個最容易上手的例子,創(chuàng)建一個 hello world:

// debug.js 文件
const greeting = 'hello nodejs debugger'
debugger
console.log(greeting)

然后運行這個文件

node --inspect-brk debug.js
Debugger listening on ws://127.0.0.1:9229/b9a6d6bf-baaa-4ad5-8cc6-01eb69e99f0a
For help, see: https://nodejs.org/en/docs/inspector

--inspect-brk 表示運行這個 js 文件的同時,在文件的第一行打上斷點。然后打開 Chrome,進入 Devtools。點擊紅框處的按鈕,就會打開一個 nodejs 專用的調(diào)試窗口,并且代碼在第一行中斷了。

nodejs 調(diào)試窗口:

這個方式的實質(zhì)是,Chrome Devtool 根據(jù) v8引擎的調(diào)試協(xié)議 向 nodejs 進程發(fā)送指令,控制代碼的運行??梢园l(fā)現(xiàn),在網(wǎng)頁的調(diào)試中,Chrome 是接受指令的一方,而在 nodejs 調(diào)試中,Chrome 轉(zhuǎn)身變?yōu)榘l(fā)送指令的一方。所謂從悲慘的乙方華麗轉(zhuǎn)身成甲方。

node 默認的 websocket 端口是 9229,如果有需要的話(比如端口被占用了),我們可以通過一些方式改變這個端口。

node --inspect=9228 debug.js
Debugger listening on ws://127.0.0.1:9228/30f21d45-9806-47b8-8a0b-5fb97cf8bb87
For help, see: https://nodejs.org/en/docs/inspector

在我們打開 Devtool 時,Chrome 默認檢查 9229 端口,但當我們改變了端口號后,就需要手動去指定 Chrome 檢查的地址了。點擊下圖中的 Configure 按鈕,輸入 127.0.0.1:9228,然后點擊 Done。這時候 Remote Target 中就會出現(xiàn) 剛才啟動的 node 進程,點擊 inspect 就可以進入調(diào)試了。

使用 VS Code 調(diào)試 Nodejs

到此為止,我們已經(jīng)達成調(diào)試 node 的目的,但還有些繁瑣,不夠自動化。我們可以使用 VS Code,來一鍵啟動調(diào)試。

用 VS Code 打開剛才的工程,然后在 launch.json 中輸入這些:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "pwa-node",
      "request": "launch",
      "name": "Launch Program",
      "skipFiles": [
        "<node_internals>/**"
      ],
      // ${file} 的意思是,當我們啟動調(diào)試的時候,調(diào)試的程序就是當前 focus 的文件。
      "program": "${file}"
    }
  ]
}

這時候切換到 index.js 文件,按 f5 啟動調(diào)試程序,當運行到第二行 debugger 語句的時候,就會自動暫停執(zhí)行。也可以點擊代碼行數(shù)的左側(cè)來打斷點。

如果想要 debug  TypeScript的,我們只需要 index.js 重命名為 index.ts,然后修改 launch.json 。

{
  "type": "pwa-node",
  "request": "launch",
  "name": "Launch Program",
  "skipFiles": [
    "<node_internals>/**"
  ],
  "program": "${file}",
  // 在調(diào)試之前,需要將 TypeScript 編譯成 JS.
  "preLaunchTask": "tsc: build - tsconfig.json",
  
  // 這里是在告訴 VS Code,編譯后的代碼文件輸出到了哪個位置。
  // 需要在 tsconfig.json 中,將 outDir 指定為 dist。
  "outFiles": [
    "${workspaceFolder}/dist/**/*.js"
  ]
}

對于 TS 調(diào)試有兩個注意點

  1. launch.json 中的 outFile 路徑,需要與 tsconfig.json 中的 outDir 保持統(tǒng)一。
  2. tsconfig.json 中將 sourceMap 指定為 true。

Conditional Breakpoint 條件斷點

在某些情況下,我們不希望打上的每個斷點都發(fā)揮作用,而是在執(zhí)行到斷點那行,且滿足某個條件再中斷代碼執(zhí)行。這就是條件斷點。

for (let i = 0; i < 10; i++) {
  console.log("i", i);
}

比如上面的代碼,假設(shè)我們在第二行 console.log 打了斷點,那么這個斷點總計會中斷十次。這往往是我們不希望看到的,可能我們需要的僅僅是其中某一次循環(huán)而非所有。這時候可以右鍵點擊并選擇 Add Conditional Breakpoint。

這時會有一個輸入框出現(xiàn),我們在其中輸入 i === 5。

這時候啟動調(diào)試,就會跳過 i 為 0 - 4,直接在在 i 為 5 的時候中斷代碼執(zhí)行?;謴?fù)代碼執(zhí)行后,會略過 i 為 6 - 9 的情況。

Conditional Breakpoint 在調(diào)試帶有大量循環(huán)和 if else 判斷時極為有用,特別是當某處的邏輯整體上是符合預(yù)期的,僅有個別特殊情況的輸出錯誤,使用條件斷點就可以略過這些正常的情況,只在個別特殊情況出現(xiàn)的時候,再中斷執(zhí)行,供我們查看各個變量是否計算正常。

總結(jié)

調(diào)試是日常工作中非常重要的能力,因為除了開發(fā)新功能外,日常有很大一部分都在調(diào)整舊的代碼,處理特別條件下的邏輯錯誤。熟練掌握調(diào)試可以很好地提升搬磚幸福感,一個復(fù)雜的 bug 卡幾小時,很容易讓人心里崩潰。但也不是說斷點調(diào)試是任何情況下都適用的銀彈,簡單的邏輯還是可以愉快地 console.log 的。文章介紹了使用 Chrome Devtools 和 VS Code 斷點調(diào)試的方法,整體上還是更推薦使用 VS Code。launch.json 只需要一次配置,后續(xù)都可以 f5 一鍵啟動調(diào)試。另外,文中提到的各種 launch.json 文件的配置,都可以使用 VS Code 自帶的工具一鍵生成。只要打開 launch.json,編輯器的右下角就會出現(xiàn) Add Configuration 按鈕,點擊就可以選擇自己需要添加的調(diào)試配置。

到此這篇關(guān)于JavaScript必備的斷點調(diào)試技巧的文章就介紹到這了,更多相關(guān)JavaScript斷點調(diào)試技巧內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論