web locks api 需配合 indexeddb 实现逻辑独占访问:锁名须含业务唯一标识且 url-safe,显式声明 exclusive 模式并 await 事务完成;safari 不支持时需 ifavailable 降级与服务端幂等兜底;锁内仅执行最小必要存储操作。

Web Locks API 不能直接“原子化”本地存储资源,但它能配合 IndexedDB 等沙箱存储机制,在多标签页、Worker 等并发场景下实现逻辑上的独占访问——关键在于把读-改-写全过程包裹在排他锁内,并依赖底层存储自身的事务语义。
锁名必须带业务唯一标识
锁的作用域由名称决定。用固定名(如 'cart' 或 'draft')会导致所有用户或所有文档互相阻塞。
- ✅ 正确:用业务主键构造锁名,例如
`user-cart-${userId}`、`note-${docId}` - ✅ 锁名需 URL-safe:避免空格、斜杠、控制字符;长度建议 ≤64 字符
- ❌ 错误:
navigator.locks.request('draft', cb)—— 所有草稿共用一把锁,失去并发意义
必须显式声明 exclusive 模式并 await 事务完成
默认 mode 是 'exclusive',但旧版 Chrome 曾静默 fallback 到 'shared',导致锁形同虚设。且锁释放时机取决于回调是否返回 Promise,不 await 事务结束会提前释放锁。
- ✅ 显式写:
{ mode: 'exclusive' } - ✅ 写操作中必须 await IndexedDB 事务完成:
await tx.done,不能只调tx.objectStore().put() - ✅ 示例结构:
await navigator.locks.request(`note-${id}`, { mode: 'exclusive' }, async () => { const db = await openDB(); const tx = db.transaction('notes', 'readwrite'); const store = tx.objectStore('notes'); const old = await store.get(id); await store.put({ ...old, updatedAt: Date.now() }); await tx.done; // 关键:确保写入真正落盘再释放锁 });
必须处理 Safari 不支持与锁不可用场景
iOS 17.5 / macOS 14.5 及更早版本的 Safari 完全不支持 Web Locks API。仅靠特性检测跳过逻辑,等于在 Safari 中放弃互斥保障。
- ✅ 必须启用
ifAvailable: true,防止 UI 卡死;锁不可用时主动降级提示(如“其他窗口正在编辑”) - ✅ 前端轻量 fallback:用
localStorage+storage事件模拟租约(非强一致,仅作友好提示) - ✅ 服务端幂等兜底是底线:每个请求附带唯一
requestId,后端校验重复提交
锁内只做最小必要操作
锁持有时间越长,排队越严重。上传、加密、DOM 渲染、日志上报等副作用必须移出锁外。
- ✅ 锁内只保留:打开 DB → 启动事务 → 读旧值 → 计算新值 → 写入 →
await tx.done - ✅ 锁外处理:UI 更新、通知发送、埋点上报、网络同步
- ⚠️ 注意:不要在锁内调用
fetch或等待用户输入,否则锁可能长时间占用
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










