1. node-debug tutorial
大家對nodejs調試應該都比較頭疼,至少我這個不用IDE寫js的人很頭疼這個,其實node的生態圈非常好 有非常好的工具和非常潮的開發方式
這里總結了3法3例,希望能對大家有所幫助
變成3種境界
- 打日志
- 斷點調試
- 測試驅動開發(tdd | bdd)
3種方法
- console.log
- 斷點調試:node debugger 或node inspector 或vscode
- 測試驅動開發
3個例子
- hello world
- 繼承例子
- express helloworld
2種模式
- Launch Program
- Attach to Process
2. 打日志
了解console上的方法,比如dir等
雖然很low,但很實用
3. 斷點調試
中規中矩,對大部分程序員應該都是比較熟悉的。無論是chrome還是eclipse,還是idea、webstorm等,只要會一種,熟悉起來就非常容易。
3.1. node debug
V8 提供了一個強大的調試器,可以通過 TCP 協議從外部訪問。Nodejs提供了一個內建調試器來幫助開發者調試應用程序。想要開啟調試器我們需要在代碼中加入debugger標簽,當Nodejs執行到debugger標簽時會自動暫停(debugger標簽相當於在代碼中開啟一個斷點)。
3.1.1. hello world例子
代碼如下:
see helloword-debug.js
var hello = 'hello'; var world = 'nodejs'; debugger; var hello_world = hello + ' ' + world; console.log(hello_world);
執行命令:node debug helloword-debug.js 就可以進入調試模式。
當然,首先需要在程序代碼中手動添加中斷debugger; , 這樣當以調試模式運行時,程序會自動中斷,然后等候你調試,就像GDB一樣,可以用help命令查看自己都可以使用哪些調試命令。
node-debug-tutorial git:(master) ✗ node debug helloword-debug.js < debugger listening on port 5858 connecting... ok break in helloword-debug.js:1 1 var hello = 'hello'; 2 var world = 'nodejs'; 3 debug> help Commands: run (r), cont (c), next (n), step (s), out (o), backtrace (bt), setBreakpoint (sb), clearBreakpoint (cb), watch, unwatch, watchers, repl, restart, kill, list, scripts, breakOnException, breakpoints, version debug> debug> n break in helloword-debug.js:2 1 var hello = 'hello'; 2 var world = 'nodejs'; 3 4 debugger; debug> repl Press Ctrl + C to leave debug repl > hello 'hello'
此時repl打開js上下文即時求值環境,和chrome的debug的console是一樣的。
如果想退出,請按下ctrl + c,這樣就可以返 到debug模式
debug> n break in helloword-debug.js:4 2 var world = 'nodejs'; 3 4 debugger; 5 6 var hello_world = hello + ' ' + world; debug> n break in helloword-debug.js:6 4 debugger; 5 6 var hello_world = hello + ' ' + world; 7 console.log(hello_world); 8 debug> n break in helloword-debug.js:7 5 6 var hello_world = hello + ' ' + world; 7 console.log(hello_world); 8 9 }); debug> repl Press Ctrl + C to leave debug repl > hello_world 'hello nodejs' > end
如果想終止調試,請按下2次ctrl + c鍵
3.1.2. 命令說明
| 可選項 | 用途 |
|---|---|
| run | 執行腳本,在第一行暫停 |
| restart | 重新執行腳本 |
| cont, c | 繼續執行,直到遇到下一個斷點 |
| next, n | 單步執行 |
| step, s | 單步執行並進入函數 |
| out, o | 從函數中步出 |
| setBreakpoint(), sb() | 當前行設置斷點 |
| setBreakpoint(‘f()’), sb(...) | 在函數f的第一行設置斷點 |
| setBreakpoint(‘script.js’, 20), sb(...) | 在 script.js 的第20行設置斷點 |
| clearBreakpoint, cb(...) | 清除所有斷點 |
| backtrace, bt | 顯示當前的調用棧 |
| list(5) | 顯示當前執行到的前后5行代碼 |
| watch(expr) | 把表達式 expr 加入監視列表 |
| unwatch(expr) | 把表達式 expr 從監視列表移除 |
| watchers | 顯示監視列表中所有的表達式和值 |
| repl | 在當前上下文打開即時求值環境 |
| kill | 終止當前執行的腳本 |
| scripts | 顯示當前已加載的所有腳本 |
| version | 顯示v8版本 |
這里就和gdb等調試器一模一樣了
回歸一下,debug的2種模式:
- js上下文即時求值環境模式
- debug斷點模式
八卦一下啊,你了解vi的3種工作模式么?
- 普通(normal)模式,又稱命令模式
- 插入(insert)模式
- 命令行(cmdline)模式
化用一下更容易理解

上面有更多的例子和api,有了上面的基礎,學習會非常簡單。
3.1.3. FAQ
注意,如果出現
< Failed to open socket on port 5858, waiting 1000 ms before retrying
請結束掉所有debug進程
ps -ef|grep debug-brk|awk '{print $2}'|xargs kill -9
3.2. node inspector
上面這種方式稍微有些麻煩,作為前端開發人員,我們寫JS代碼調試的時候一般都用FireBug或Chrome瀏覽器內置的調試工具,其實nodejs程序也可以這樣子來調試,但是首先需要安裝一個node-inspector的模塊。
node-inspector是通過websocket方式來轉向debug輸入輸出的。因此,我們在調試前要先啟動node-inspector來監聽Nodejs的debug調試端口。
3.2.1. 安裝
這個需要用npm來安裝,只需要執行下列語句:
npm install -g node-inspector
安裝完成之后,通常可以直接這樣啟動在后台:
node-inspector &
默認會監聽8080端口,當然,也可能通過使用--web-port參數來修改。然后,在執行node程序的時候,多加個參數:--debug-brk, 如下:
node --debug-brk app.js
或者
node-debug app.js
控制台會返回“debugger listening on port 5858”, 現在打開瀏覽囂,訪問http://localhost:8080/debug?port=5858,這時候就會打開一個很像Chrome內置調試工具的界面,並且代碼斷點在第一行,下面就可以使用這個來調試了。
常用調試功能
- 增加斷點,查看調用棧,變量等
- 使用console打印查看日志
使用方法和chrome的inspect element調試web開發是一樣的。
調試還是很方便的,而且可以遠程調試。其實原理很簡單,它啟動的是一個web server,我們要做的就是把localhost換成對應ip即可,要注意服務器的防火牆哦。
3.2.2. 測試extend.js
測試一下繼承是否ok,首先執行命令,打印出結果,但這種辦法才挫了
➜ node-debug-tutorial git:(master) node extend.js node debug hello node debug
開始使用node-inspector調試
3.2.2.1. 啟動
➜ node-debug-tutorial git:(master) node-debug extend.js Node Inspector is now available from http://localhost:8080/debug?port=5858 Debugging `extend.js` debugger listening on port 5858
3.2.2.2. 界面說明

mac系統大部分人都記不住這些按鍵,下面給出說明
| Symbol | Key |
|---|---|
| ⌘ | Command Key |
| ⌃ | Control Key |
| ⌥ | Option Key |
| ⇧ | Shift Key |
斷點操作
- resume script execution(F8) 掛起斷點,也可以理解為放棄當前斷點,如果有下一個斷點,會自動斷住得
- step over(F10) 跳過這行,到下一行,如果當前函數結束,會跳到調用棧的上一級的下一行
- step into(F11) 進入當前行代碼里的函數內部
- step out(Shift + F11) 從當前函數退出到之前進入的代碼處
控制台操作
- 不能使用var,直接打印變量傑克
3.2.2.3. 增加斷點,並打印出this

3.2.2.4. 斷點下一步,並打印出this

3.2.2.5. 結論
通過
base.call(this);
這行代碼,明顯看到test對象的this被改變了,即使test擁有了base的所有屬性和方法,這是最簡單的實現繼承的方法,當然多重繼承mixin也可以是這樣的原理
3.2.3. 測試express helloworld
這種測試一般都是看request里的params,query和body等
准備工作
npm init . npm install --save express touch express-helloworld.js
測試express-helloworld.js代碼
var express = require('express'); var app = express(); app.get('/',function(req,res){ res.send('hello,world'); }); app.listen(5008);
執行,安裝服務器自動重載模塊
npm install -g supervisor supervisor express-helloworld.js
打開瀏覽器訪問http://127.0.0.1:5008/就會看到helloworld返回
此時終止supervisor express-helloworld.js,使用ctrl + c終止。
然后使用node-inspect調試
➜ node-debug-tutorial git:(master) ✗ node-debug express-helloworld.js Node Inspector is now available from http://localhost:8080/debug?port=5858 Debugging `express-helloworld.js` debugger listening on port 5858
增加斷點

使用curl來模擬get請求,增加一個參數test,便於一會的debug
curl -G -d "test=string" http://127.0.0.1:5008/
此時瀏覽器頁面會停在斷點處,在console里輸入req.query即可以查到參數

3.3. vscode
為什么選用vsc,一個原因就是因為調試
- node-inspector雖好,項目已大特別慢,這方面vsc做了不少優化
- tdd/bdd雖好,還不能完全實現
vsc官方說
We improved stepping performance by loading the scopes and variables of stack frames lazily. This improvement is based on a protocol change that affects all debug adapters.
意思就是他們做了很多優化
使用中,確實比node-inspector快很多
vsc調試使用方法也很簡單,步驟如下:
- 打開要調試的文件,按f5,編輯器會生成一個launch.json
- 修改launch.json相關內容,主要是name和program字段,改成和你項目對應的
- 點擊編輯器左側長得像蜘蛛的那個按鈕
- 點擊左上角DEBUG后面的按鈕,啟動調試
- 打斷點,盡情調試(只要你會chrome調試,一模一樣)

更多示例,參見https://github.com/i5ting/vsc
4. 測試驅動開發
和斷點調試思維相反,先寫測試用例,知道自己要實現什么效果,再去寫代碼。所以不是很容易接受。而且一旦重構,就要重寫測試,也是比較痛苦的。但測試對軟件的穩定性和質量是至關重要的。所以一旦習慣測試,你會愛不釋手。
- tdd
- bdd
- 代碼覆蓋率
4.1. 測試框架
- nodeunit
- mocha
- ava
- jest
4.1.1. 更多測試
npm install --save-dev chai npm install --save-dev sinon npm install --save-dev supertest npm install --save-dev zombie
4.1.2. 代碼覆蓋率
修改Gulpfile.js
- auto test
- 代碼測試覆蓋率
npm install --save-dev gulp npm install --save-dev gulp-mocha npm install --save-dev gulp-istanbul
創建gulpfilejs
var gulp = require('gulp'); var istanbul = require('gulp-istanbul'); var mocha = require('gulp-mocha'); gulp.task('test', function (cb) { gulp.src(['db/**/*.js']) .pipe(istanbul()) // Covering files .on('finish', function () { gulp.src(['test/*.js']) .pipe(mocha()) .pipe(istanbul.writeReports()) // Creating the reports after tests runned .on('end', cb); }); }); gulp.task('default',['test'], function() { gulp.watch(['./db/**/*','./test/**/*'], ['test']); }); gulp.task('watch',['test'], function() { gulp.watch(['./db/**/*','./test/**/*'], ['test']); });
測試
node_modules/.bin/gulp 這時,你試試修改測試或源文件試試,看看會不會自動觸發測試
當然,如果你喜歡只是測試一次,可以這樣做
node_modules/.bin/gulp test 如果你不熟悉gulp,可以再這里https://github.com/i5ting/js-tools-best-practice/blob/master/doc/Gulp.md學習
修改package.json
"scripts": { "start": "./node_modules/.bin/supervisor ./bin/www", "test": "./node_modules/.bin/mocha -u tdd" },
4.2. 資源
- debugger官方文檔
-
https://github.com/baryon/tracer
-
http://www.habdas.org/node-js-debugging-primer/
-
https://github.com/visionmedia/mocha
-
http://visionmedia.github.io/mocha/
-
http://mochajs.org/
-
https://github.com/chaijs/chai
-
http://chaijs.com/
-
http://sinonjs.org/
-
http://zombie.labnotes.org/
-
https://github.com/tj/supertest(api test文檔)
-
https://github.com/tj/superagent/blob/master/test/node/agency.js(api test示例)
-
https://github.com/i5ting/js-tools-best-practice/blob/master/doc/Gulp.md
-
https://github.com/SBoudrias/gulp-istanbul
5. 2種模式
5.1. Launch Program
簡單說,就是直接執行,上文最簡單的斷點調試都屬於這種模式
5.2. Attach to Process
簡單說,是調試某個已啟動的線程
比如,我在終端里,node --debug啟動了某個程序,
node --debug app.js Debugger listening on 127.0.0.1:5858
這樣就啟動了debugger,然后你就可以在vscode或者node inspector里attach里

