在纷繁复杂的代码世界中,出错是难免的,也许在传统的前端代码中,你习惯于 console 来排查问题,这是不合理的,在现代的社会下,调试代码是你最快找到问题的方法。
这篇文章就是教你如何快速的使用调试找到问题。查找和识别错误的速度越快,你下班的时间就越早:)。
在当前 Node.js v15 版本下,以前非常多的调试方式已经失效了,Node.js 传统的调试协议也进行了许多升级,我们按照最新的方式,来告诉你如何调试。
众所周知,代码是写(调)出来的,而不是猜出来的。
如果不通过调试运行代码,那么意味着需要去猜测代码中发生的事情,YY 一下,如果代码运行到这个地方,这个值可能是什么。使用调试的主要好处就是可以观察程序的运行情况,而不用做假设,可以一次跟随程序执行一行代码。
另一方面,你可以控制代码执行的逻辑,你可以暂定执行,或者逐行运行,甚至修改内存中的值,让它走到另一个分支里。
使用 Node.js 内置的调试方式是最简单直接的,但是现阶段都有 IDE,所以大家都不太关心底层的实现,一键开启调试就行了。
而实际上 IDE 的调试都是基于这个内置调试之上的。
在了解内置的 Node.js 调试方式之前,我们先来了解一下另一个概念:断点(breakpoint)。
顾名思义,断点就是能断住代码执行的点,一般情况下,它的表现真的是个点。
比如 vscode 里的断点(红红的点,十分醒目)。
image.png
断点会强制任何 JavaScript 调试器在给定点暂停。这样就可以让代码执行到这个地方停下,观察这行代码以及之后代码里的变量值。
让我们回归传统,在没有 IDE 的情况下(比如文本编辑器,Vim 啥的),都是使用 debugger
语句来让打断点的。
您使用调试器语句。您可以在代码的任何位置添加此语句,比如:
async function initMethod() {
debugger;
console.log('bbb');
}
initMethod();
这样,我们就希望调试的时候会在这一行停下来。
光有断点还不行,普通情况下,Node.js 会忽略这个 debugger,只有开了调试模式才会暂停到这一行(原因是调试器太强大,有些恶意行为可以通过它注入代码)。
通过给 node 增加 --inspect
参数才会开启调试模式,这个模式下,还会开放一个默认的 9229 端口,允许其他 IDE 接入。
这个模式下,会输出下面的信息:
Debugger listening on ws://127.0.0.1:9229/d598ab05-88e8-433f-b641-bf2766da97f5
For help, see: https://nodejs.org/en/docs/inspector
ws://127.0.0.1:9229/d598ab05-88e8-433f-b641-bf2766da97f5
是暴露的调试链接,里面包含了协议,host,端口和一个唯一的 uuid。这是一个标准 v8 调试协议。
我们执行一下这个命令。
咦,为啥什么反应都没有,代码直接执行结束了,脑中一个大大问号?
事实上,仅仅开启调试还是不够的,调试器还没有接收到足够的信息,或者说没有一个展现调试的地方。
node 还提供了另一个会卡住的调试命令。--inspect-brk
会停在代码的第一行,等待下一步的指示,用他就行了。
但是这只是普通的卡住代码,我们需要能支持 v8调试协议的 UI。
有许多种方法可以作为 UI,而最简单的就是我们电脑上一般都会有的 Chrome 浏览器。
Chrome 自带了一个调试页 chrome://inspect/
,打开后,如果是在本机,会直接列出可调式的端口和文件地址(如果在远程,也可以配置 ip)。
点击这个 inspect
,添加我们的项目后,蓝色的断点条就乖乖的展现到眼前了。
这个时候,我们就可以进行单步调试了(不需要 debugger 了)。
在 Chrome UI 打开的时候,控制台会输出一句话。
表明这个调试协议已经连上了 node 开启的调试端口。
我们总结一下,整个调试分为两个部分,“开启 node 调试端口” + “符合 v8调试协议的调试器 attach 到调试端口”。
VSCode 是我们最常用的 IDE,集成了调试的 UI,所以我们不再需要开启 Chrome 来调试了。
本质和最基本的一样,开启调试端口,连接调试端口。只是 VSCode 本身是个编辑器,可以直接在其之上打断点,集成度更高,这也是为什么我们一般都使用 IDE 的缘故。
VSCode 提供了一个调试 UI,需要用户配置一个 launch.json(等价于启动命令)。
image.png
内容如下,核心是 runtimeExecutable
使用的命令,以及 runtimeArgs
参数,这里不再需要 --inspect
了(IDE内部会处理)。
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [{
"name": "test",
"type": "node",
"request": "launch",
"cwd": "${workspaceRoot}",
"runtimeExecutable": "node",
"runtimeArgs": [
"test.js"
],
"console": "integratedTerminal",
"protocol": "auto",
"restart": true,
"port": 7001,
"autoAttachChildProcesses": true
}]
}
在上面的配置字段中有个 request
字段,有两个值可以选择:launch
和 attach
, 它表示VS Code中核心的两种调试模式。
launch 指的是直接由编辑器启动(直接 fork 一个进程),比如我们这个示例,而 attach 表示服务已经启动,我们是 attach 到原来那个进程中,比如上面的 Chrome 调试。_ 然后打上断点,执行就行了。
执行的时候,我们发现命令行会发现一段话。
cd /Users/harry/project/application/my_midway_app ; /usr/bin/env 'NODE_OPTIONS=--require "/Applications/Visual Studio Code.app/Contents/Resources/app/extensions/ms-vscode.js-debug/src/bootloader.bundle.js" --inspect-publish-uid=http' 'VSCODE_INSPECTOR_OPTIONS={"inspectorIpc":"/var/folders/xw/yl56_kmj5nd_r0cql7rcv8640000gn/T/node-cdp.94650-2.sock","deferredMode":false,"waitForDebugger":"","execPath":"/Users/harry/.nvs/default/bin/node","onlyEntrypoint":false,"autoAttachMode":"always","fileCallback":"/var/folders/xw/yl56_kmj5nd_r0cql7rcv8640000gn/T/node-debug-callback-02a1ac2abe751152"}' /Users/harry/.nvs/default/bin/node test.js
第一个 cd 忽略,我们主要看看中间这段。VSCode 启动的时候加载 bootloader.bundle.js
这个文件,然后传了一堆 IPC 启动参数,比如创建了一个 sock 文件,其余的把 launch 里的参数翻译了一下传入。
核心就是这个 bootlaoder
文件,由于 VSCode 是 ts 写的,这个文件的源码在这。
https://github.com/microsoft/vscode-js-debug/blob/ca280351b2/src/targets/node/bootloader.ts
最核心的代码是 inspectOrQueue
方法,代码如下,其中有几个特别关键的地方。
function inspectOrQueue(env: IBootloaderInfo): boolean {
// 省略
// 如果没有传 --inspect,则开启调试端口
const openedFromCli = inspector.url() !== undefined;
if (!openedFromCli) {
// if the debugger isn't explicitly enabled, turn it on based on our inspect mode
if (!shouldForceProcessIntoDebugMode(env)) {
return false;
}
inspector.open(0, undefined, false);
}
const info: IAutoAttachInfo = {
ipcAddress: env.inspectorIpc || '',
pid: String(process.pid),
telemetry,
scriptName: process.argv[1],
inspectorURL: inspector.url() as string,
waitForDebugger: true,
ppid: String(env.ppid ?? ''),
};
if (mode === Mode.Immediate) {
// 同步模式,直接跟着应用启动,监听调试端口
spawnWatchdog(env.execPath || process.execPath, info);
} else {
// 异步模式,等进程启动,attach 监听端口
const { status, stderr } = spawnSync(
env.execPath || process.execPath,
[
'-e',
`const c=require("net").createConnection(process.env.NODE_INSPECTOR_IPC);setTimeout(()=>{console.error("timeout"),process.exit(1)},10000),c.on("error",e=>{console.error(e),process.exit(1)}),c.on("connect",()=>{c.write(process.env.NODE_INSPECTOR_INFO,"utf-8"),c.write(Buffer.from([0])),c.on("data",e=>{console.error("read byte",e[0]),process.exit(e[0])})});`,
],
{
env: {
NODE_SKIP_PLATFORM_CHECK: process.env.NODE_SKIP_PLATFORM_CHECK,
NODE_INSPECTOR_INFO: JSON.stringify(info),
NODE_INSPECTOR_IPC: env.inspectorIpc,
},
},
);
}
// 省略
return true;
}
不管是异步还是同步的模式,其原理都是 Node.js 最基础的 “开启端口”,“连接调试端口” 这两个步骤。VSCode 还会考虑到别的场景,比如代码创建子进程时,会将子进程也自动添加调试参数,方便自动 attach 等。
在这里,我们会发现一个新的名词,叫 AutoAttach
。这是 VSCode 在 2018 年 7 月提出的新名词,微软表示用户基本都不太会写 launch.json 文件,经常写错(没错,就是我),所以为了简化写法,特地做的新功能。
这个功能怎么用呢?
简单的来说,只要启动的 node 加上 --inspect
命令,VSCode 就能自动监视到,并且 attach 到进程里开启调试,不再需要复杂的配置。
开启的命令加到了选项里(cmd+shift+p 搜索)。
有几种附加方式。 比较常用的是仅带标志。
这样我们只要在 VSCode 终端里输入任意带有 --inspect
的命令,就会自动被断点到了,很香。
调试到这里基本就讲完了,所有的调试的原理都是一样的,藉由 Node.js 原生的打开调试端口的能力,不同的 IDE 才能连接到该端口,进而做出更加强大的能力。
比如 VSCode 不仅仅能做传统的调试,也能增加配置,在执行调试前后增加钩子,执行自己的命令,这都是扩展能力的体现。
相信你看完这篇文章,对 Node.js 应用的调试方式有了一定的理解,写出更好的代码。
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/494q1a3eTBVO1UZ1QKBWiA
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。