4、Console面板进阶:console.log技巧、console.table、console.time、条件断点

说实话,很多开发者对 Console 面板的认知,就停留在 console.log 打几个变量。但你要知道,这玩意儿远比你想象的强大。我在 Electron 项目里调试过不少诡异的问题,Console 面板用得好,能省下你大把抓头发的时间。

今天咱们就聊聊几个进阶玩法。嗯,都是我在实战中反复用到的。

4.1 console.log 的那些隐藏技巧

先说说 console.log 本身。你以为它只能打印一个值?其实它能干的事多着呢。

4.1.1 格式化输出

我个人习惯用 %s、%d、%o 这些占位符。举个例子:

const appName = 'Electron调试器';
const version = 2.1;
console.log('当前应用:%s,版本号:%d', appName, version);

这样输出清晰多了。尤其是 %o,可以展开对象的所有属性,比直接打印对象方便不少。

4.1.2 带样式的日志

你可以在日志里加 CSS 样式。我在项目中经常用它来区分不同模块的日志:

console.log('%c[主进程]', 'color: #2196F3; font-weight: bold', '应用启动成功');
console.log('%c[渲染进程]', 'color: #4CAF50; font-weight: bold', '页面加载完成');

这样一眼就能看出日志来自哪个进程。调试 Electron 的多进程架构时,这招特别好使。

小技巧: 你可以把样式封装成一个函数,比如 logMain(msg) 和 logRenderer(msg),这样就不用每次都写样式字符串了。

4.1.3 分组日志

当你要打印一堆相关日志时,用 console.group 把它们收起来:

console.group('用户登录流程');
console.log('开始登录...');
console.log('验证凭据...');
console.log('登录成功');
console.groupEnd();

在 Console 面板里,这些日志会折叠成一个组,点击就能展开。我经常用它来追踪一个完整的事件链路。

4.2 console.table:数据展示神器

这个我必须重点说说。以前调试数组或对象时,我都是 console.log 然后手动展开。直到有一次,我需要查看一个包含 50 条用户数据的数组……

嗯,那次之后我就彻底爱上了 console.table。

const users = [
  { id: 1, name: '张三', age: 28, role: 'admin' },
  { id: 2, name: '李四', age: 32, role: 'user' },
  { id: 3, name: '王五', age: 25, role: 'editor' }
];
console.table(users);

输出结果会是一个漂亮的表格,每一列对应对象的属性,每一行对应一个对象。你想想看,如果数据有几十条,用表格展示是不是一目了然?

你还可以指定只显示某些列:

console.table(users, ['name', 'role']);

这样只显示姓名和角色两列,数据量大的时候特别有用。

核心要点: console.table 适用于数组和对象。数组的索引会作为表格的第一列,对象的键名会作为列标题。数据量在 100 条以内时效果最佳。

4.3 console.time:精准测量代码性能

调试 Electron 应用时,性能问题是个大头。比如某个操作卡顿了,你得知道到底是哪一步慢。

console.time 和 console.timeEnd 就是干这个的。用法很简单:

console.time('数据加载');
// 模拟数据加载
for (let i = 0; i < 1000000; i++) {
  // 一些计算
}
console.timeEnd('数据加载');

控制台会输出类似 数据加载: 12.345ms 这样的结果。你可以给不同的操作起不同的名字,同时测量多个时间点。

我曾经在 Electron 项目里用它来排查 IPC 通信的延迟问题:

// 主进程
console.time('IPC: 获取用户数据');
ipcMain.handle('get-users', async () => {
  const data = await db.query('SELECT * FROM users');
  console.timeEnd('IPC: 获取用户数据');
  return data;
});

这样就能精确知道 IPC 调用花了多少时间。是数据库查询慢,还是数据传输慢,一目了然。

注意: console.time 和 console.timeEnd 的标签必须完全一致,否则不会输出结果。另外,不要在生产环境保留这些代码,它们会影响性能。

4.4 条件断点:精准定位问题

普通断点有个问题:如果代码在循环里执行了 1000 次,你每次都要手动点「继续」?那不得累死。

条件断点就是解决方案。你可以在断点上设置一个条件,只有条件满足时才会暂停。

设置方法很简单:

  1. 在 Sources 面板中找到你要打断点的行
  2. 右键点击行号,选择「Add conditional breakpoint」
  3. 输入条件表达式,比如 index === 500

举个例子,假设你在处理一个数组,想看看第 500 个元素是什么:

for (let i = 0; i < 1000; i++) {
  processData(data[i]); // 在这里设置条件断点:i === 500
}

这样程序只会在 i 等于 500 时暂停,其他时候正常执行。省时省力。

条件断点还可以用更复杂的表达式。比如我只想在用户 ID 大于 100 且角色是 admin 时暂停:

user.id > 100 && user.role === 'admin'
避坑指南: 我曾经在条件断点里写了一个耗时的函数调用,结果每次循环都要执行这个函数,反而把程序搞得更慢了。所以条件表达式尽量简单,不要写复杂的逻辑。

4.5 综合实战:调试 Electron 的 IPC 通信

最后,咱们把这些技巧串起来,看看怎么调试一个真实的 Electron 场景。

假设你的应用有个功能:从主进程获取用户列表,然后在渲染进程展示。如果数据加载很慢,你可以这样调试:

// 渲染进程
console.time('获取用户列表');
const result = await ipcRenderer.invoke('get-users');
console.timeEnd('获取用户列表');

console.table(result, ['id', 'name', 'email']);

// 如果某个用户数据异常,设置条件断点
// 比如只关注 ID 为 42 的用户

这样你就能同时看到:

  • 整个 IPC 调用花了多少时间
  • 返回的数据结构是否完整
  • 特定用户的数据是否正确

嗯,这就是 Console 面板进阶用法的精髓。别小看这些技巧,它们能让你在调试时少走很多弯路。下次遇到问题,试试这些方法,你会发现调试效率提升不少。