在只有一格信号的铁皮棚里发帖:纯 JS 离线写入队列实战
来源:dev.to — 2026-09-06
📋 概述
作者运营的船坞建造日志站(boatbuildlog.com)最关键的场景,是用户在只有一格甚至完全没有信号的铁皮棚、谷仓或车道上用手机记录当天进度。因此「一次 POST 失败」不是网络小麻烦,而是意味着用户辛苦写下的一段记录直接丢失,他们会就此放弃记录——功能不是降级而是死亡。文章由此立下铁律「提交绝不可以在失败时毁掉用户输入」,并详细分享了离线队列的工程取舍:用 IndexedDB 而非 localStorage 存储含照片的日志(Blob 而非 base64);重放时现取新 CSRF token 而非连同草稿一起存储;以及一个让修复两次都不生效的 service worker 缓存 bug——因为缓存键只匹配了 pathname,丢了查询串。
🔑 核心要点
- 核心铁律:如果丢失用户输入会毁掉你要养成的习惯,写入路径就需要队列而不是重试按钮——这正是 IndexedDB 离线队列存在的理由
- 用 IndexedDB 而非 localStorage,因为日志几乎都是照片:localStorage 只能存字符串,把几张 4MB 手机照片 base64 塞进 5MB 配额不是办法;Blob 还能扛过浏览器重启
- CSRF token 绝不能随草稿一起存:队列里的条目可能搁置数天,token 早已过期,重放被拒后看起来就像队列本身的 bug;正确做法是重放时抓取 composer 页面读取全新 token
- service worker 缓存键必须是完整请求:/css/app.css?v=1755 与 ?v=9902 都归一到同一 pathname 命中旧缓存,导致每次部署求了新 URL 却仍拿到安装期旧文件,作者同一修复发了两遍都被告知无效
- 会大声失败的资产有人上报,静默失败的资产需要测试:改一次未带 ?v= 戳的 JS(登录表单的 PoW 求解器)后,老访客一直用旧 challenge 对上新服务端,注册悄悄停摆、毫无报错
💡 金句
如果丢一次用户的输入对你要养成的那个习惯是致命的,那么写入路径需要的是一个队列,而不是一个重试按钮。
👍 0
👎 0
← 返回 dev.to 首页