Отладчик node debug
Следующая наша тема касается отладки под Node.JS. Первым делом мы рассмотрим самый простой, встроенный отладчик, который называется «node debug».
Выглядит это так: допустим у нас есть скрипт
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var http = require('http'); var url = require('url'); var server = new http.createServer(); server.on('request', function(req, res){ var urlParsed = url.parse(req.url, true); if (req.method == 'GET' && urlParsed.pathname == '/echo' && urlParsed.query.message){ res.end(urlParsed.query.message); return; } res.statusCode = 404; res.end('Not Found'); }); server.listen(1337); console.log("Server is running"); |
например server.js который упорно глючит и мы хотели бы остановит его выполнение на некотором моменте, чтобы посмотреть переменные и посмотреть что происходит. Для этого мы в этом месте ставим «debugger»
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
var http = require('http'); var url = require('url'); var server = new http.createServer(); server.on('request', function(req, res){ var urlParsed = url.parse(req.url, true); debugger; if (req.method == 'GET' && urlParsed.pathname == '/echo' && urlParsed.query.message){ res.end(urlParsed.query.message); return; } res.statusCode = 404; res.end('Not Found'); }); server.listen(1337); console.log("Server is running"); |
и запускаем скрипт в режиме отладки —
1 |
C:\node\server> node debug server.js |
никаких модулей для этого ставить не надо
Запустил. Изначально скрипт находится в состоянии паузы, видите ничего не происходит. В режиме отладки есть некоторые команды, например «help» —
«help» нам вывел их список, мне сейчас нужна команда «cont». «cont» продолжит выполнение —
Видите, он продолжил и даже вывел в console — «Server is running».
Отлично, что ж, давайте откроем браузер и перейдем по этой ссылке — http://127.0.0.1:1337/
Опа, как только я зашел, произошло событие ‘request’, запустился обработчик и выполнение остановилось, как раз на команде «debugger».
теперь я могу перейти в консоль «repl» — режим выполнения команд и например, выяснить, что такое «urlParsed»
например запустить что то — «res.end(«Uahahaha!»)
Теперь заглянем в браузер, помните у нас там страничка ждет пока мы ей что то передадим
Дождалась!
Надо сказать, что встроенный отладчик который мы с вами рассмотрели, это самое простое, что только бывает. Его используют в тех редких случаях, когда более продвинутые способы отладки, почему то не работают, ну или когда лень их запускать. Гораздо удобнее осуществлять отладку используя инструменты разработчика в браузере Chrome.
Отладка под браузером Chrome
Для этого нам понадобится утилита которая называется «node inspector». Поставим ее глобально
приготовления завершены и теперь несколько слов о том, что сейчас будет происходить. У Node.JS, при запуске, есть специальный параметр «—debug» после которого можно дать файл скрипта для запуска
1 |
C:\node\server> node --debug server.js |
когда Node.JS запускается с этим параметром, то он не только запускает server.js, но Node.JS так же начинает слушать происходящее на этом порту — «5858». К этому порту может подключиться другая программа и давать команды Node.JS, относящиеся к отладке. Например приостановить выполнение, возобновить выполнение, получить текущее значение какой то переменной и так далее. Эти команды выдаются в соответствии со специальным протоколом, который описан в документации к «V8» — https://github.com/v8/v8/wiki/Debugging%20Protocol. Например, вы можете посмотреть примеры команд в доке, вот такая команда
1 |
{"seq":117,"type":"request","command":"continue"} |
означает продолжить выполнение, или вот такая команда
1 |
{"seq":117,"type":"request","command":"evaluate","arguments":{"expression":"1+2"}} |
говорит Node.JS вычислить 1+2. Мы конечно же эти команды вручную набирать не будем, хотя могли бы, а используем утилиту node-inspector которая как раз будет посылать эти команды, а нам предоставлять красивый веб интерфейс.
Итак, оставлю Node.JS здесь запущенным
и открою новое окно консоли, в котором запущу node-inspector.
node-inspector — это веб сервер к которому можно подсоединиться под этим урлом — http://127.0.0.1:8080/?port=5858, который он дает и работать с отладчиком. То есть я буду слать команды веб серверу node-inspector, а он будет транслировать их как раз ноде, которая слушает протокол отладки, используя язык отладки «V8».
Итак я зашел в node-inspector
Этот дизайн похож на встроенный инструмент разработки, хромовский, но на самом деле это не они. Они похожи, поскольку вот эти стили HTML взяты из того же движка, соответственно интерфейс очень похож, но на самом деле это всего лишь веб страница, которую нам отдает node-inspector. Теперь я зайду в отдельном окошке на страницу http://127.0.0.1:1337/echo?message=TEST, вернувшись в интерфейс отладчика мы увидим
Произошло следующее — когда я перешел по этому адресу, то сработала функция обработчик request — это та функция которая передается вторым параметром методу «server.on()»
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
var http = require('http'); var url = require('url'); var server = new http.createServer(); server.on('request', function(req, res){ var urlParsed = url.parse(req.url, true); debugger; if (req.method == 'GET' && urlParsed.pathname == '/echo' && urlParsed.query.message){ res.end(urlParsed.query.message); return; } res.statusCode = 404; res.end('Not Found'); }); server.listen(1337); console.log("Server is running"); |
Если бы Node.JS был запущен без флагов отладки, то команда debugger была бы проигнорирована, но в нашем случае она сработала, V8 приостановил выполнение JavaScript и послал node-inspector, который подключен к ноде по этому порту — «5858», об этом информацию. Node-inspector ее получил и при помощи протокола «WebSocket», с которым мы познакомимся далее, переслал ее в браузер, браузерному JavaScript. Здесь уже отреагировал на это веб интерфейс и показал мне, что вот тут остановка
Этот же веб интерфейс, запросил данные об остановке, которыми я могу воспользоваться, видите, ходить тут могу
При этом node-inspector берет на себя трансляцию моих действий в команды для отладчика V8. Могу даже использовать консоль, посмотреть «urlParsed»
Все есть. Или если я хочу ответить на запрос, то я могу сделать так же как делал со встроенным отладчиком, а именно вызвать метод в текущем контексте — «res.end(«Uahahaha! Test passed»);»
Когда я наотлаживался, я могу play сделать
придется нажать дважды, потому что favicon будет запрашиваться.
при следующем запросе
опять управление перейдет сюда
как говориться, отлаживай, не хочу. Можем пошагово продолжать выполнение
Все очень удобно, этим рекомендуется пользоваться. Единственное рекомендуется иметь ввиду, что мы работаем с цепочкой соединений. Мы зайдя в данный url к node-inspector — «http://127.0.0.1:8080/?port=5858», присоединяемся из клиентского, браузерного JavaScript к серверу node-inspector, серверный node-inspector присоединяется к Node.JS и бывает так, что какое то из этих соединений рвется, соответственно отладка перестает работать, в этом случае можно перезайти на страницу отладки, если это не помогло, рестартовать node-inspector, если это не помогло, то рестартовать по цепочке все — ноду, node-inspector и перезайти на страницу в браузере и тогда точно все будет хорошо.
Давайте рассмотрим важнейший сценарий отладки, а именно отладку при возникновении ошибок в JavaScript.
Например при обработке запроса есть неизвестный вызов или что то еще, от чего JavaScript падает
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var http = require('http'); var url = require('url'); var server = new http.createServer(); server.on('request', function(req, res){ var urlParsed = url.parse(req.url, true); WTF(); if (req.method == 'GET' && urlParsed.pathname == '/echo' && urlParsed.query.message){ res.end(urlParsed.query.message); return; } res.statusCode = 404; res.end('Not Found'); }); server.listen(1337); console.log("Server is running"); |
сейчас я запущу этот сервер — раз
два
три
Сколько действий.
Теперь, если я перейду по адресу сервера — «http://127.0.0.1:1337/», то никакой отладки не произойдет, потому что JavaScript просто упадет. Для того чтобы отлаживать JavaScript в этом случае, можно зайти в отладчик и здесь кликнуть то же самое, что мы кликаем в отладчике в браузере
то есть сделать эту пимпочку фиолетовой. Теперь перехожу на эту страницу — «http://127.0.0.1:1337/» и отладчик останавливается на ошибке
Давайте взглянем на еще один пример отладки, на этот раз консольной утилитой.
В файле pow.js есть вычисление степени при помощи такой вот рекурсивной функции.
1 2 3 4 5 6 7 8 9 10 |
function pow(x, n){ if(n<0){ return x; } var result = x * pow(x, n-1); return result; } console.log( pow(2, 3)); |
и при вызове она должна вывести, как видим, два в третьей степени
Но выводит 32. А два в третьей это, как известно, восемь. В чем же дело? Чтобы посмотреть, что происходит, попробуем запустить отладчик.
Теперь если я попробую запустить node-inspector, то он запустится, но на самом деле ничего отлаживаться не будет. Почему? Так как мы понимаем происходящее, то можем это легко объяснить. Ведь нода запустилась, открыла доступ по порту «5858», а потом выполнила скрипт и все. Нода закончила свою работу, она уже все вывела и все и никакой node-inspector теперь к ней не подключится, ну просто потому что она не запущена. Порт 5858 закрыт. Что делать? То что нам на самом деле нужно — это другой флаг «debug-brk», он запускает скрипт сразу входя в состояние останова.
Вот я запустил, оно подняло отладчик и теперь ждет пока кто нибудь к нему подключится и даст команду продолжить выполнение. Теперь я для верности перезапущу node-inspector, который запущен в отдельном окне.
И войдем в инструменты разработки через Chrome. Открываю соответствующий url
И вижу, где произошла текущая остановка, и далее я буду рассказывать достаточно подробно для тех, кто возможно впервые сталкивается с подобным инструментом разработки.
По центру находится текущий скрипт, справа находится информация и кнопки управление процессом. Сейчас я нажму вот сюда
Эта кнопка или клавиша F11 переведет управление на следующую команду. Нажимаю
Хм, куда же мы попали? Здесь немножко тонкий момент, дело в том, что когда я попытаюсь подключить объект «console», то Node.JS его require, мы видим это на изображении, это встроенный объект по умолчанию не подключается, а тут вот нужно его подключить. Процесс подключения console нас не очень интересует, по этому я нажму другую кнопку, вот эту
которая означает, что процесс выполнения нужно продолжить, но остановиться как только произойдет выход из этой функции. На изображении мы видим, что после того как я нажал на эту кнопку node-inspector нам показал, что console подключен и следующий вызов обратится к pow(). Жмем F11 или кнопку step to next function
вот мы находимся внутри функции pow(), и теперь повторные нажатия будут переводить управление внутрь вложенных вызовов нажму несколько раз
видите «Call Stack» растет. «Call Stack» это последовательность сложенных вызовов функции которые привели к текущему положению дел. Соответственно в данном случае из списка Call Stack нас интересует pow.js, это единственный наш файл, остальное показаны встроенные всякие модули. Если мы выделим какой либо из вызовов pow.js, из списка Call Stack, мы увидим, что различаются он локальными переменными.
Дальнейшие шаги по отладке очевидны, по этому мы переходим дальше, а именно к отладке под IDE.
Отладка под IDE
В качестве IDE будет использоваться WebStorm и для того, чтоб запустить отладку нам вполне подойдет уже готовая конфигурация,
Единственное нужно будет, чтоб запускалась именно нода, а не supervisor!
Чтобы запустить отладку жму сюда
И смотрю в консоле, что у меня получилось. При запуске в режиме отладки, WebStorm добавляет к Node соответствующий параметр «—debug-brk» и указывает ему значение, это значение это порт на котором нода должна ожидать подключение отладчика, по умолчанию — 5858. Ранее к этому порту подключался node-inspector, но сейчас к этому порту подключен сам WebStorm. Соответственно он реализует необходимый интерфейс и сейчас если я зайду в браузере на этот url — «http://127.0.0.1:1337/echo?message=TEST» и перейдем в окно WebStorm, то увидим
То произойдет остановка, и здесь, в окне Variables, я могу ходить, анализировать переменные смотреть urlParsed и так далее.
Резюме по способам отладки для Node.JS
Первый способ, это запуск node debug script. При этом нода тут же приостанавливает выполнение скрипта и переходит в специальный режим консольной отладки. В котором можно получит список команд, через «help», управлять выполнением скрипта, переходить в режим консоли через «repl». Это работает, но уж больно просто. Хочется какой то более удобный интерфейс, по этому в тех случаях когда это возможно используется отладка под браузером Chrome, через node-inspector либо под IDE. Для того чтобы такая отладка стала возможной нужно запустить ноду со специальным флагом «—debug» либо «—debug-brk», последний при этом, переведет скрипт в состояние остановки тут же. Если нода запущена с этими флагами, то она дает доступ к встроенному механизму отладки V8, соответственно V8 начинает слушать этот порт, по умолчанию 5858, отладчик к нему подключается и может слать команды которые управляют выполнением, получать текущие переменные и так далее. Для отладки под браузером Chrome в качестве отладчика можно использовать node-inspector, который с одной стороны подключается к порту ноде и умеет говорить с ней, с другой стороны он показывает страничку в Chome и принимает через нее команды, вместо Chrome могут быть другие браузеры, достаточно современные. Ну а относительно IDE я могу сказать то что смотря какая у вас IDE, как в ней все сделано, это может быть удобно, может не удобно, лично для меня наиболее безглючным и надежным способом, как правило, является отладка через Chrome, но для нее нужно запускать node-inspector.
Продолжает выполнения скрипта с текущего момента в обычном режиме. Если скрипт не встретит новых точек останова, то в отладчик управление больше не вернётся.
noc-pkg-pyclips для отладки скриптов не требуются, поэтому, их отсутствие на работоспособности не скажется.