题干与适用场景
一个已安装的 PWA 要在应用图标显示未读数量。请说明 Badging API 的能力探测、更新与清除流程,以及浏览器不支持或调用失败时的降级方案。
面试官考察点
- 是否知道
navigator.setAppBadge()与clearAppBadge()只在支持的安全上下文中可用。 - 是否区分页面与 Service Worker 的
WorkerNavigator能力,并处理返回 Promise 的失败。 - 是否把 API 当作提示层,而不是未读数据的事实来源。
- 是否提供标题、站内计数和可访问名称等可感知降级,并控制频繁更新。
回答前需要澄清的问题
- 目标是已安装 PWA 的应用图标,还是普通浏览器标签页?
- 未读数量的权威来源、刷新策略和多标签页一致性是什么?
- 是否需要离线更新、后台推送,以及哪些浏览器和操作系统必须覆盖?
- 屏幕阅读器用户如何获得同等信息,数量是否需要脱敏或截断?
30 秒回答框架
我会把徽章当作可选提示层。只在 HTTPS 下探测 navigator.setAppBadge,以服务端同步的未读数更新,检查 Promise 失败;数量为零时调用 clearAppBadge。不支持或失败时保留站内未读计数、标题或 favicon 标记,并用可访问文本表达状态。页面和 Service Worker 共享同一计数协议,更新做节流,不能因为徽章失败阻塞消息读取。
分步骤深入解答
1. 明确能力与显示边界
Badging API 面向已安装 Web 应用的图标;W3C 2026 草案将 setAppBadge 与 clearAppBadge 放在 Navigator 和 WorkerNavigator 上。它是安全上下文能力,浏览器可以不实现或改变显示形式,因此不能承诺跨平台显示精确数字。
2. 以权威未读数驱动更新
客户端从服务端或本地同步层取得非负整数,先做上限与去重,再调用 navigator.setAppBadge(count)。count 为 0 时可调用 clearAppBadge();若只想显示有未读标记,也可不传数字。每次调用都处理 Promise rejection,记录能力和错误类型,不记录消息内容。
3. 设计页面与后台路径
前台页面可在收到同步事件后更新;Service Worker 处理后台事件时使用 self.navigator 的对应能力(以实际浏览器支持为准)。两条路径都只能写入同一版本化计数,避免旧事件覆盖新数值。应用重新打开时重新拉取权威数量,不能把图标徽章当数据库。
4. 失败降级与无障碍
能力缺失、非安全上下文、未安装或调用失败时,保留应用内未读列表、导航栏计数和文档标题提示,并在界面提供可读文本,例如“有 3 条未读消息”。aria-live 只播报变化且要节流,避免把视觉徽章当作唯一通道。徽章失败不影响消息读取与已读操作。
高质量示范回答
我会先确认产品要覆盖的是已安装 PWA 图标,而不是普通标签页。HTTPS 页面探测 navigator.setAppBadge,以服务端同步的非负未读数驱动更新,零值调用 clearAppBadge,并捕获 Promise 失败。页面和 Service Worker 都只消费同一版本化计数,应用启动时重新同步,避免旧事件覆盖新值。Badging API 支持有限且平台可能把大数显示成标记,所以我同时保留站内计数、标题或 favicon 降级,并用节流后的可访问文本让屏幕阅读器获得相同状态。徽章只是提示层,失败不能阻塞消息读取。
常见错误
- 把 Badging API 当成所有浏览器标签页都支持的精确数字显示。
- 未检查 HTTPS、安装状态、方法存在性或 Promise rejection。
- 将徽章数量作为未读数据的唯一存储,导致刷新或多设备不一致。
- 页面和 Service Worker 各自维护计数,旧事件覆盖新状态。
- 只提供图标颜色变化,没有标题、站内计数或可访问文本降级。
- 每条消息都立即调用 API,造成抖动、耗电和无意义更新。
追问及应对
为什么不能只更新 favicon?
favicon 只影响标签页或书签,不能表达已安装应用图标状态。应把 Badging API、favicon、标题和站内计数组合成按能力选择的提示层。
传入 4000 会显示什么?
用户代理可以把大数压缩成 99+ 等形式,也可以只显示标记,因此产品应限制显示上限并在站内提供准确数字。
如何测试降级?
覆盖安全上下文与非安全上下文、未安装 PWA、缺少方法、Promise rejection、零值清除、后台事件乱序和屏幕阅读器文本;每种情况都验证消息数据链路仍可用。