同一台真实设备、同一路数据,在两个页面上表现完全不同:

  • 「实况数据」页面:正常显示,数字在跳。
  • 「调试窗口」页面:一片空白,什么都没有。

这两个页面消费的是同一份数据。所以问题不可能出在"数据源"上—— 它已经证明了数据是通的。剩下的可能性只在于:数据在这条链路上被丢掉了一次

01先做三个对照,把范围缩到一种组合

手上有两个变量可以拨动:端口(8081 / 8082)和数据来源(真实设备 / 模拟数据)。 两个变量各两个取值,四种组合,我做了三次——因为其中一种就是坏掉的那个:

端口数据来源结果
8081真实设备调试窗口空白
8082真实设备正常
8081模拟数据正常

这张表比它看起来有用得多,因为它一次排除了两个方向:

  • 8081 这个端口本身没问题——换成模拟数据它就好了。 所以不是端口配错、不是被占用、不是防火墙。
  • 真实设备的数据本身没问题——换到 8082 它就好了。 所以不是设备没在发、不是格式不合法。

问题被逼进了一个很窄的角落:「8081 端口上的、真实设备发来的那份数据」。 前两个变量都无罪,有罪的只能是这个组合里的具体内容。

这是我目前最依赖的排查手法:把所有变量摆成一张表,用最少的实验次数, 排除掉尽可能多的嫌疑。三次实验的代价,换来了"三个方向里只有一个还需要查"。

02第一个猜想:值没变,所以界面没重绘

范围缩小之后,我猜了第一个原因:数据本身没变化

前端有个很常见的坑——如果新值和旧值完全一样,很多渲染逻辑会认为"没必要更新", 于是界面保持原样。空白可能是"从来没画过第一帧", 因为第一帧到来的数据就已经"等于初始值"了。

这个猜想符合当时的表象,但我没有立刻去改代码。 因为"数据没变化"和"数据没到达"是两件事,症状却一模一样。 要分清它们,得往链路的上游走一步。

03把链路拆成三个问题

一条数据链路上有三个位置可能会断,我把它们写成三个必须回答的问题:

  1. 到底有没有触发转发? —— 数据到了,回调函数被执行了吗?
  2. 转发的目标地址是什么? —— 就算执行了,它发去了正确的地方吗?
  3. 转发的内容是什么? —— 就算发对了地方,发出去的东西是对的吗?

为了让第一个问题能被回答,我在控制台加了一行转发日志。 如果日志都不出现,那后面两个问题就没有意义——这是最省时间的做法: 先确认这条路上有没有人,再问他带了什么。

04一动手就撞到的事:两个同名的函数

准备去找这个回调函数的时候,我搜了一下它的名字。结果出来两条:

全局搜索 onAtmosphericDataReceived
src/dataManager.js    →  function onAtmosphericDataReceived(data) { ... }
    src/manager.js        →  function onAtmosphericDataReceived(data) { ... }

同一个函数名,两份互相独立的实现。

这意味着一个很糟的可能性:我刚才如果在 dataManager.js 里改了逻辑、加了日志, 而运行时实际执行的是 manager.js 里那一份——那我做的一切都是白费, 而且屏幕上不会有任何提示告诉我"你改错了地方"。

确认到底哪一个在跑
// 在函数体第一行打印调用栈,最直接
    console.trace('onAtmosphericDataReceived called');
    // 控制台会告诉你调用它的那条路径经过了哪个文件

这类问题的隐蔽之处在于:改代码这件事本身是"成功"的。 保存没报错、编译没报错、编辑器里看到的就是你写的那些字。 唯一不对的是——你改的不是会运行的那一份。

05为什么会有两个同名函数

回头看,这几乎是一个必然的结果,而不是意外:

  • 先写了一个,后来重构又写了一个。 老的那份没有立刻删——"先留着,万一还要用"。于是它一直在那儿。
  • 两份代码的文件名都很合理。 dataManagermanager, 单看名字谁都不像垃圾。
  • 没人真的用过"搜索"这个动作。 如果当初写过一行 import 或者一次全局搜索,这个重复立刻就会暴露。

所以我现在养成了一个习惯:改一个函数之前,先全局搜它的名字。 如果搜出来不止一处,先弄清楚哪一份在跑,再动手。 这一步大概花十秒,能省掉一个下午。

06这件事留下的三句话

  1. 两个变量就用表格铺开。 三种组合跑一遍,就能排除掉大部分方向。这比"凭感觉先改一处试试"快得多。
  2. 先确认有没有人,再问他带了什么。 链路上先验证"函数有没有被调用",再去看"内容对不对"。 顺序反了,就会在数据的细节里迷路。
  3. 改代码之前先搜索这个名字。 同名实现是静默的——它不会报错,只会让你的修改石沉大海。

至于最初那个空白窗口,我最后还是回到了"值没变所以没重绘"这条线上。 但如果没有前面对链路的确认,我连"值到底有没有到达"都不知道, 改重绘逻辑也只是在赌。

关于本文
整理自 2025 年 9 月 22 日的一段便签。原始记录是散点的排查条目 (对照结果、三个待查问题、以及"两个同名函数"这个发现), 这里的结构是事后重排的。
2026.09.20 整理
原文只写了"系统中有两个不同的 onAtmosphericDataReceived 实现"这一句。 重读时我觉得这一句才是整段记录里最值钱的部分,所以单独给它一节。