代表性面试主题

前端面试:如何用 Cookie Store API 与 Service Worker 同步状态?

前端困难
Offer.cc 编辑团队发布 更新

题干

一个离线优先网页需要在 Service Worker 中感知登录 Cookie 变化,并更新缓存策略。请设计 Cookie Store API 方案,说明订阅范围、事件语义、竞态和不支持浏览器的降级。

题干与适用场景

一个离线优先网页需要在 Service Worker 中感知登录 Cookie 变化,并更新缓存策略。请设计 Cookie Store API 方案,说明订阅范围、事件语义、竞态和不支持浏览器的降级。

Cookie Store API 提供异步的 Cookie 读取与写入,并允许 Service Worker 订阅匹配的 Cookie 变化。它适合替代阻塞式的 document.cookie 读取,但不会改变 Cookie 的同源、路径、Secure、HttpOnly 或 SameSite 约束。

面试官考察点

重点包括:区分页面 API 与 Service Worker 的订阅 API、理解 cookiechange 只报告脚本可见变化、按名称和 URL 过滤、处理重复订阅与事件竞态,以及避免把 Cookie 当作可靠的跨上下文数据库。

澄清问题

先确认 Cookie 是否 HttpOnly、作用域是否跨路径、页面与 Service Worker 是否同源,以及目标浏览器支持情况。再问登录、登出和刷新是否可能并发发生,缓存更新是否必须实时,离线期间允许多长时间使用旧会话状态。

30 秒回答框架

“我会在 Service Worker 注册时订阅需要的 Cookie 名称和 URL,收到 cookiechange 后只重新读取相关 Cookie,并让缓存策略通过单调版本或会话状态机更新。Cookie Store API 是异步 API,事件只覆盖脚本可见的变化,也不提供事务或全局顺序保证;因此处理器必须幂等、去重并重新读取当前状态。对不支持的浏览器,我会保留网络请求中的 Cookie 校验和页面端显式同步,绝不把旧缓存当成已登录证明。”

分步骤深入解答

第一步:明确 API 边界

页面可通过 window.cookieStore 异步读取和写入 Cookie;Service Worker 则通过 registration.cookies 管理订阅,并接收 cookiechange 事件。两者都受浏览器 Cookie 策略约束,无法读取 HttpOnly Cookie 的值。

第二步:按最小范围创建订阅

订阅应指定必要的 Cookie 名称,并在确实需要时限定 URL。名称相同但路径不同的 Cookie 可能同时存在,处理器必须依据事件中的变更信息和当前 URL 重新确认目标,而不是只按名字猜测。

javascript
self.addEventListener("activate", (event) => {
  event.waitUntil(
    self.registration.cookies.subscribe([
      { name: "session", url: self.registration.scope },
    ]),
  );
});

第三步:理解事件不是值快照

事件包含变化的 Cookie 集合,但异步处理时 Cookie 可能已经再次变化。收到事件后应重新调用 get()getAll() 读取当前状态,并把处理设计为幂等;不要把事件对象当作事务日志或最终真相。

第四步:区分脚本可见与 HttpOnly 变化

规范只要求脚本可见的 Cookie 变化触发相关通知。服务器设置或删除 HttpOnly Cookie 后,Service Worker 不能读取其值,也不应从缺少通知推断会话没有变化。认证结论仍需由服务器响应决定。

第五步:建立会话状态机

把状态定义为未知、已验证、已登出或过期,并使用响应中的版本、过期时间或重新验证结果推进状态。Cookie 变化只触发重新检查,不直接等同于登录成功或注销完成。

第六步:处理并发与跨标签页竞态

多个页面可能同时刷新或删除 Cookie。处理器应合并短时间内的通知,按当前读取结果执行一次缓存更新,并用会话版本避免旧事件覆盖新状态。缓存删除与预缓存写入也应具备幂等性。

第七步:设计不支持浏览器的降级

如果浏览器没有 Cookie Store API,页面可以在关键导航或网络响应后显式发送同步信号,服务器仍以 Cookie 验证为准。不要通过轮询 document.cookie 读取 HttpOnly 值,也不要因为 API 缺失就放宽缓存认证条件。

第八步:限制隐私和安全暴露

订阅只覆盖业务需要的名称与 URL,避免将 Cookie 值写入日志、Cache Storage 或 postMessage。设置 Cookie 时继续使用 Secure、HttpOnly、SameSite、Path 和合理的过期时间,并在登出时同时清理客户端缓存。

高质量示例答案

我会把 Cookie Store API 当作变化提示器,而不是认证数据库。Service Worker 激活时,为特定名称和作用域创建订阅;收到 cookiechange 后重新读取当前脚本可见状态,进入幂等的会话状态机,并通过会话版本更新或清理缓存。HttpOnly Cookie 的值始终由服务器响应验证,事件缺失也不代表会话没有变化。多个页面同时刷新时合并通知,避免旧事件覆盖新状态。对不支持的浏览器,保留关键请求的服务器校验与页面端显式同步,不能用 document.cookie 轮询替代 HttpOnly 保护。所有订阅和缓存操作都限制作用域,并覆盖登出、过期、离线和 Service Worker 更新场景。

常见误区

把 cookiechange 当成完整审计日志

事件是通知,不提供跨进程事务序列。处理器必须重新读取当前状态并支持重复执行。

认为 Service Worker 能读取 HttpOnly Cookie

HttpOnly 仍禁止脚本读取。Service Worker 只能通过网络请求让服务器验证会话,不能从 Cookie Store API 获得秘密值。

用 Cookie 变化直接决定缓存认证

Cookie 变化可能来自刷新、过期或不同路径。缓存策略应等待服务器验证和版本状态,不能把任意变化当作登录或登出结论。

延伸追问与参考答案

同名 Cookie 位于不同 Path 时如何避免误删?

在订阅和读取时保留 URL 作用域,删除时使用精确的 name、URL、Path 与其他属性。若无法确认目标 Cookie,就让服务器通过响应完成清理,不发送宽泛删除操作。

Service Worker 更新期间订阅会不会丢失?

在新的 Worker 的 activate 阶段幂等地确保订阅存在,并在迁移时读取当前 Cookie 状态重建缓存。不要依赖旧 Worker 的内存状态;更新完成后重新执行初始化。

离线时 Cookie 过期但没有网络,缓存该怎么办?

把本地状态标记为待验证并限制离线能力,不能延长服务器会话。恢复网络后先执行认证请求,再决定恢复、清理或降级缓存。

公开来源

同类题目