使用 Visual Studio Code 进行调试
在计算机上打开 Visual Studio Code,并使用以下代码创建名为 currency.js
的新文件:
const rates = {}; function setExchangeRate(rate, sourceCurrency, targetCurrency) {
if (rates[sourceCurrency] === undefined) {
rates[sourceCurrency] = {};
} if (rates[targetCurrency] === undefined) {
rates[targetCurrency] = {};
} rates[sourceCurrency][targetCurrency] = rate;
rates[targetCurrency][sourceCurrency] = 1 / rate;
} function convertToCurrency(value, sourceCurrency, targetCurrency) {
const exchangeRate = rates[sourceCurrency][targetCurrency];
return exchangeRate && value * exchangeRate;
} function formatValueForDisplay(value) {
return value.toFixed(2);
} function printForeignValues(value, sourceCurrency) {
console.info(`The value of ${value} ${sourceCurrency} is:`); for (const targetCurrency in rates) {
if (targetCurrency !== sourceCurrency) {
const convertedValue = convertToCurrency(value, sourceCurrency, targetCurrency);
const displayValue = formatValueForDisplay(convertedValue);
console.info(`- ${convertedValue} ${targetCurrency}`);
}
}
} setExchangeRate(0.88, 'USD', 'EUR');
setExchangeRate(107.4, 'USD', 'JPY');
printForeignValues(10, 'EUR');
要保存该文件,请按“Ctrl+S”(Windows、Linux)或“Cmd+S”(Mac)。
此程序的目标是设置三种货币(USD、EUR 和 JPY)之间的汇率。 然后,我们要显示 10 EUR
对应于其他所有货币的价值,精确到小数点后两位。 对于添加的每种货币,应计算与所有其他货币的汇率。
创建启动配置
我们会经常用到调试器,因此让我们为应用创建一个启动配置。 在 Visual Studio Code 中,转到“运行”选项卡,选择“创建 launch.json 文件”,然后选择“Node.js”。
这就在项目中创建了文件 .vscode/launch.json
。 可以编辑此文件,以进一步自定义如何启动程序进行调试。 默认情况下,将创建启动配置以执行当前打开的文件。 在本示例中,该文件为 currency.js
。
检查程序入口点的路径和名称是否与设置相匹配。
备注
如果要为项目创建不同的启动配置,选择“添加配置”。
完成配置准备后,若要选择它,请使用边栏顶部的下拉列表。 接下来,要开始调试,请选择“运行”。
分析问题
现在,要启动该程序,请选择“启动调试”。
应看到程序快速完成。 这是正常的,因为尚未添加任何断点。
如果没有显示调试控制台,若要打开它,请按“Ctrl+Shift+Y”(Windows、Linux)或“Cmd+Shift+Y”(Mac)。 应在调试控制台中看到此文本,后跟一个异常。
The value of 10 EUR is:
11.363636363636365
- 11.363636363636365 USD
/app/node-101/currency.js:23
return value.toFixed(2);
^
TypeError: Cannot read property 'toFixed' of undefined
at formatValueForDisplay (/app/node-101/currency.js:23:16)
at printForeignValues (/app/node-101/currency.js:32:28)
at Object.<anonymous> (/app/node-101/currency.js:40:1)
at Module._compile (internal/modules/cjs/loader.js:959:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
at Module.load (internal/modules/cjs/loader.js:815:32)
at Function.Module._load (internal/modules/cjs/loader.js:727:14)
at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10)
at internal/main/run_main_module.js:17:11
此程序所要做的是设置三种货币(USD、EUR、JPY)之间的汇率,并显示 10 EUR
对应于其他所有货币的值,精确到小数点后两位。
在这里可以看到两个 bug:
- 小数点后不止两位。
- 程序崩溃并出现异常,无法显示
JPY
值。
修复位数显示
首先,我们将解决第一个问题。 由于你没有编写此代码,并且调用了许多不同的函数,因此让我们首先使用分布执行来了解执行流。
使用断点并逐步执行
要添加断点,请单击 上第 39 行的左边距。
然后再次启动调试,并单步执行 printForeignValues()
函数。
检查变量状态
现在,使用“变量”窗格检查不同变量的值。
value
和sourceCurrency
的值是多少?- 你是否在
rates
变量中看到三个预期的项:USD
、EUR
和JPY
?
要继续单步执行直至设置变量 convertedValue
,请使用“单步跳过”。
应该看到此时该值似乎正确。
进一步看看 displayValue
的值。 它应该包含要显示的格式化字符串,如我们预期的那样有两个数字。
然后我们可以得出结论,到目前为止,函数 convertToCurrency()
和 formatValueForDisplay()
似乎是正确的,并返回了预期的结果。
更正错误
继续单步执行直到 console.info()
调用,并仔细检查此行。 看到这里的错误了吗?
然后你可以在打印值时使用 displayValue
而不是 convertedValue
来修复第一个 bug。 重启程序并检查 USD
值是否正确显示 11.36
。 第一个问题解决了。
找出崩溃的原因
现在让我们弄清楚程序崩溃的原因。 删除当前断点,并选中“断点”窗格中的 框,以强制程序在引发异常后暂停。
在调试器中再次运行该程序。 它应在出现异常时暂停,并在编辑器窗口的中间显示一个大型错误日志。
查看执行停止和显示异常消息 TypeError: Cannot read property 'toFixed' of undefined
的行。 通过该消息可以推断,value
参数函数的值是 undefined
而不是数字,因此导致了异常。
倒回调用堆栈
你在错误消息下面看到的堆栈跟踪可能有点难以理解。 好消息是,Visual Studio Code 会为你处理函数调用堆栈。 默认情况下,“调用堆栈”窗格中只会显示有意义的信息。 让我们使用它来找出导致此异常的代码。
我们知道 formatValueForDisplay()
引发了异常。 要查看调用它的位置,请在“调用堆栈”窗格中双击它下面的函数。 应在 printForeignValues
函数中的此行结束。
const displayValue = formatValueForDisplay(convertedValue);
仔细观察,你会发现导致异常的参数来自于 convertedValue
变量。 现在,需要找出该值在何时变为 undefined
。
一种选择是在此行添加一个断点,并在断点每次命中该变量时检查它。 我们不知道何时会发生这种情况,在复杂的程序中,这种方法可能很麻烦。
添加条件断点
此处最好将调试器设置为仅在 convertedValue
为 undefined
时才在该断点处停止。 事实上,Visual Studio Code 可以做到这一点。 不通过左键单击在 31
行添加常规断点,而是右键单击并选择“添加条件断点”。
现在可以输入触发断点的条件。 输入 convertedValue === undefined
,然后按 Enter。 重启程序,它应在你希望的位置停止。
观察当前状态
现在,请花一些时间来分析当前状态。
- 变量
convertedValue
是convertToCurrency(value, sourceCurrency, targetCurrency)
的结果,因此还要检查参数的值并确认它们是正确的。 - 具体而言,请查看
value
是否具有预期的值10
。
查看一下 convertToCurrency()
函数的代码。
function convertToCurrency(value, sourceCurrency, targetCurrency) {
const exchangeRate = rates[sourceCurrency][targetCurrency];
return exchangeRate && value * exchangeRate;
}
你知道此代码的结果为 undefined
。 还知道 value
为 10
。 这意味着问题应该出在 exchangeRate
的值。 将鼠标悬停在变量 rates
之上查看该值。
你尝试获取 EUR
到 JPY
的汇率,但如果展开 EUR
值,你会发现只有 USD
的转换率。 缺少 JPY
的转换率。
修复缺失的转换率
现在已知缺失某些转换率,让我们来了解原因。 要删除所有现有断点,请在“断点”窗格中选择“删除所有断点”。
观察汇率变量
在程序的开头第 37
行的 setExchangeRate(0.88, 'USD', 'EUR');
上添加一个断点。 重启程序,若要监视 rates
变量的值,请在“监视”窗格中选择“加号”并输入 。 每次更新 rates
的值时,其值都会反映在“监视”窗格中。
单步跳过第一个 setExchangeRate()
调用,并查看 rates
上的结果。
此时可以看到 USD
和 EUR
的互汇率相同,符合我们的预期。 现在再单步跳过一次,看看第二次 setExchangeRate()
调用的结果。
你会看到 USD
和 JPY
的互汇率相等,但并未显示 EUR
和 JPY
之间的汇率。 现在来看看 setExchangeRate()
代码。
function setExchangeRate(rate, sourceCurrency, targetCurrency) {
if (rates[sourceCurrency] === undefined) {
rates[sourceCurrency] = {};
} if (rates[targetCurrency] === undefined) {
rates[targetCurrency] = {};
} rates[sourceCurrency][targetCurrency] = rate;
rates[targetCurrency][sourceCurrency] = 1 / rate;
}
最重要的是最后两行。 看来你找到 bug了! 仅在 sourceCurrency
和 targetCurrency
之间设定了汇率,但还需要计算之前添加的其他货币的汇率。
修复代码
替换以下两行:
rates[sourceCurrency][targetCurrency] = rate;
rates[targetCurrency][sourceCurrency] = 1 / rate;
替换为此代码。
for (const currency in rates) {
if (currency !== targetCurrency) {
// Use a pivot rate for currencies that don't have the direct conversion rate
const pivotRate = currency === sourceCurrency ? 1 : rates[currency][sourceCurrency];
rates[currency][targetCurrency] = rate * pivotRate;
rates[targetCurrency][currency] = 1 / (rate * pivotRate);
}
}
使用此代码,对于 sourceCurrency
和 targetCurrency
以外的每种货币,将使用 sourceCurrency
的汇率来推断另一种货币与 targetCurrency
之间的汇率,并相应地进行设置。
备注
只有当 sourceCurrency
和其他货币之间的汇率已经存在时,此修复才有效,在本例中,这是一个可以接受的限制。
测试更正
我们来测试一下更改。 删除所有断点,然后重启程序。 现在应在控制台中看到预期的结果,而不会出现任何故障。
The value of 10 EUR is:
- 11.36 USD
- 1220.45 JPY
就是这样。 代码修复了。 现在,你可以使用 Visual Studio Code 高效调试事先不了解的代码。 干得不错!
使用 Visual Studio Code 进行调试的更多相关文章
- Mac上使用Visual Studio Code开发/调试.NET Core代码
Mac上使用Visual Studio Code开发/调试.NET Core代码 .Net Core 1.0终于发布了,Core的一大卖点就是跨平台.这个跨平台不只是跨平台运行,而且可以跨平台开发.今 ...
- SharePoint Framework 在Visual Studio Code中调试你的本地解决方案
博客地址:http://blog.csdn.net/FoxDave Visual Studio Code不知道大家都有没有,界面清爽,编辑快速,是一个非常好的前端开发工具.本文介绍如何使用Goog ...
- 如何用Visual Studio Code远程调试运行在服务器上的nodejs应用
假设我有一个nodejs应用,运行在AWS - 亚马逊云平台上(Amazone Web Service).我想用本地的Visual Studio Code来远程调试服务器端的nodejs应用. Vis ...
- 在Mac上使用Visual Studio Code开发/调试.NET Core代码
.Net Core 1.0终于发布了,Core的一大卖点就是跨平台.这个跨平台不只是跨平台运行,而且可以跨平台开发.今天抽空研究了下在Mac下如何使用VS Code来开发.NET Core程序,并且调 ...
- visual studio code 里调试运行 Python代码
最近对微软的visual studio code 挺感兴趣的,微软的跨平台开发工具.轻量简洁. 版本迭代的也挺快的,截止16年8月2日已经1.3.1版本了,功能也愈加完善.(16年12月18日 已经, ...
- SharePoint Framework 在Visual Studio Code中调试你的托管解决方案
博客地址:http://blog.csdn.net/FoxDave 上一篇介绍了如何在本地调试你的SharePoint Framework解决方案,本篇介绍如何调试你的SharePoint Onl ...
- [翻译]使用Visual Studio Code怎样调试Rust
我将 Visual Studio Code 作为Rust首选编辑器.遗憾的是 VS Code 不能非常好地完成 Rust 的调试. 配置调试器不难,但仍然需要几个步骤.我已经完整配置了好几次.我正在写 ...
- Visual Studio Code 断点调试配置方法(请按我的步骤 一定可以做到)
1 visual studio code 的 extentions 里安装插件 debugger for chrome2 devtool: 'eval-source-map', cacheBustin ...
- Visual Studio Code如何调试代码
首先安装扩展调试插件debugger for chrome 点击瓢虫按钮,进行调试项目的配置,点击配置按钮 选择Chrome环境, 会弹出Chrome调试配置文件launch.json,修改下端口即可 ...
- visual studio code断点调试react
在项目配置文件 .vscode\launch.json 中添加: "sourceMaps": true, "skipFiles": [ &quo ...
随机推荐
- spring上 -基于注解配置bean,动态代理,AOP笔记
用的是jdk8,spring框架里jar包的下载可以自己搜到 注解用到的jar包. 60,注解配置Bean快速入门 基本介绍 代码结构: UserDao.java package com.hspedu ...
- 云原生爱好者周刊:Lens 5.2 发布,支持 M1 芯片
云原生一周动态要闻: Lens 5.2 发布 CNI 1.0.1 发布 K8ssandra 从 Helm 迁移到 Operator Amazon EKS Anywhere – 现在普遍可用于在本地创建 ...
- 云原生爱好者周刊:这款支持全平台的 Podman Desktop 值得一试
开源项目推荐 Podman Desktop Companion Podman 桌面客户端,支持 macOS.Windows 和 Linux 平台,后端支持原生 Podman(仅支持 Linux).Po ...
- Edge缓存清理操作说明
1. 打开Edge浏览器 2. 点击屏幕右上角三个点的按钮 3. 在出现的菜单里面选择"设置" 4. 在出现页面里面左侧选择"隐私.搜索和服务",然后右侧点击& ...
- ESP32+L298N+MQTT+4G无线远程监控+四驱动小破车
ESP32+L298N+MQTT+4G无线远程监控+四驱动小破车 小车源代码 注意修改WIFI 信息 #include <analogWrite.h> #include <WiFi. ...
- C240817D. 模拟赛:树上dp(以i为起点)+set操作
C240817D. 模拟赛 比较显然的树上dp, 但是维护set比较烦 考场上其实自己是定义 \(f[i]\) 是以 \(i\) 结尾, 然后这样的话单次更新根本做不到 \(O(logN)\). 反应 ...
- games101_Homework6
实现 Ray-Bounding Volume 求交与 BVH 查找 在本次编程练习中,你需要实现以下函数: • IntersectP(const Ray& ray, const Vector3 ...
- VMware使用Ubuntu20.04时发生屏幕闪烁
问题:VMware使用Ubuntu20.04时发生屏幕闪烁 分析:这是由于虚拟机里面的显示器不支持3D加速问题导致的 解决方法:关闭虚拟机 → 左上角菜单 → 虚拟机 → 设置 → 显示器 → 取消勾 ...
- Android WebView 加载 html页面 实现 不同分辨率 不同 dpi 缩放自适应处理 解决方案
两种情况一起使用 实现 不同分辨率 不同 dpi 缩放自适应处理 //webview 需要配置 mWebView.getWebSetting().setUseWideViewPort(true);// ...
- 基于 Github 平台的 .NET 开源项目模板 - PR 相关
本篇将介绍开源模板的 PR 相关功能配置 赘述 project.yml 使用周期 文件来源: 运行跟目录下的 scanner.bat/sh 生成的. 文件位置: .github\project.yml ...