沉默失败先装嘴律 · 够不到的环境,先给它一层能看见的报错 · v1
入档:2026-08-21 来源:zombie-world 的 iOS 触屏问题 —— 玩家反馈只有「走不动、开不了枪」, 连改两轮都没中,因为手机上一处 throw 就是整块功能静默消失,而看不到那行报错 验证状态:⭐⭐ 二次验证(同一项目两轮 + 同轮第三处,见下;跨项目未验证)
一句话律
当一个失败不报告任何原因时,第一件该修的不是那个 bug,是「它不说话」这件事。
判据很好认:如果你能拿到的全部信息就是「就是不行」,那你接下来做的每一次修改都是猜。 猜中了你也不知道为什么中,猜不中你连排除了什么都不知道。
事故形态:连改两轮,都在盲改
玩家反馈 iOS 上「走不动、开不了枪」,而换枪、开菜单都正常。
- 第一轮(2026-08-20):判断是触点回收漏了,写了一套触点对账。没中。
- 第二轮(2026-08-21):判断是异常吃掉了触摸链,做了结构性加固。至今不知道中没中。
两轮之间隔了一天,共同点是:我手上没有 iOS 设备,改完了验不了, 而那台设备回来的信息永远只有「还是不行」。
真正的问题不在这两个判断哪个对——而在于在装上观测手段之前,它们都只是候选。
手机、App 内嵌 WebView、投影仪、别人的电脑,这些环境的共同点是没有控制台:
一处 throw 会把后面所有代码一起带走,页面看起来只是「某块功能没了」,
没有任何东西告诉你发生过异常。
修法:把「不能观测」当成第一优先级的缺陷
第二轮的修改里,真正有长期价值的不是那几处 try/catch,而是这三层:
1. 在所有脚本之前,装一层会显示到屏幕上的错误捕获
<!-- 必须放在其它 script 之前,且自身不依赖任何东西 -->
<script>
window.addEventListener('error', function(e){
showRedBar('脚本出错:' + e.message + ' @ ' + e.filename + ':' + e.lineno);
}, true);
window.addEventListener('unhandledrejection', function(e){ /* 同上 */ });
</script>
关键是显示到屏幕,不是 console——够不到的设备上,console 等于不存在。
红条只在真出错时出现,正常构建里永远看不到它。
2. 给关键链路做一份能截图的账目
触摸链路加了计数器(收到几次 / 认领几次 / preventDefault 执行几次 / 第一条报错是什么),
做成一个可开关的浮层。判读规则写在代码注释里,别人截一张图就能定位断在哪一环:
live 一直是 0 → 事件根本没进来
start 涨、claim 不涨 → 被判成「落在 UI 上」了
pd < claim → preventDefault 没生效(事件不可取消)
顶上出现 ERR 那一行 → 直接就是答案
3. 报错要说「为什么」,不能只说「失败了」
联机连不上时原来只有一句「联机服务器连接中断」,等于没说。
浏览器不让脚本看到 WebSocket 握手的 HTTP 状态码——那就绕一下:
连不上时去探一次 /healthz,探得通说明服务器活着、是握手被拒(多半是来源不在白名单),
探不通才是网络问题。拿不到直接证据时,用一个能拿到的旁证把可能性分开。
判据:什么时候值得先装探针
装探针要花时间,不是每次都划算。触发条件是你够不到出问题的那个环境:
| 情况 | 做法 |
|---|---|
| 本机能复现 | 别装,直接断点/日志更快 |
| 够不到设备,但对方能配合操作 | 装,做成「打开开关 → 截图发我」 |
| 够不到设备,对方也不会操作 | 装成默认可见的(如出错才出现的红条) |
| 一次都没成功观测过 | 探针优先于修复,先别改业务代码 |
成本比较通常很悬殊:装一层错误显示大约十几行,而一次盲改要付出 「改 → 打包 → 提交审核 → 等过审 → 请人测 → 得到『还是不行』」的完整往返。 在这种项目里,一次盲改的代价远高于一层探针。
与相邻几条律的分工
- 全站文字截断体检_检测工具本身要先被证伪_v1:那条讲你有工具,但工具在骗你; 本条讲你根本没有工具,所以只能收到「就是不行」。两条是一件事的两端: 先要有观测,再要怀疑观测。
- 交付前实测证伪律_v1:那条要求交付前主动去证伪自己的结论; 本条是它的前置条件——够不到的环境里,你连证伪的手段都得先造出来。
- 约束型结论先复核律_文档写的不可能会过期_v1:同一个项目里的另一条教训。 两条合起来是:别信旧结论,也别信没有观测的新结论。
反例 / 边界
- 能复现的问题不适用。本机能稳定复现时,装探针纯属绕远路。
- 不要把探针做成永久的界面负担。默认关闭、或只在出错时出现; 开关不要记进 localStorage——它是排查用的,不该有人下次进来还开着。
- 探针本身也可能骗人。它同样受 全站文字截断体检_检测工具本身要先被证伪_v1 管辖: 这一轮就有一次,诊断按钮做在了「操作说明」最底部,而那一屏在 iOS 上滚不动, 等于装了个够不到的探针。装完要问一句:出问题的那个人,够得到它吗?
关联文档
- 本律的来源案例:2026-08-21_一小时分享会_从设计到投影现场_全链路复盘_v1
- 同项目上一轮的教训:约束型结论先复核律_文档写的不可能会过期_v1
- 一体两面:全站文字截断体检_检测工具本身要先被证伪_v1
- 交付纪律:交付前实测证伪律_v1
- 复盘的事实纪律:复盘事实先行原则