PWA开发中使用idb封装库在Service Worker内无法向IndexedDB存储数据
导致IndexedDB写入失败的常见原因如下:
- Service Worker 异步任务未被生命周期托管
你当前的IndexedDB写入操作是在fetch事件的响应返回后异步执行的,没有用event.waitUntil()包裹整个写入任务链。Service Worker会在respondWith返回的Promise完成后就可能被销毁,未执行完的写入操作会直接被中断,这是最可能的原因。
修正逻辑参考:
if(event.request.url.indexOf(url) >= 0) { event.respondWith( fetch(event.request).then(res => { const clonedResponse = res.clone(); // 把写入操作的Promise链交给waitUntil托管,避免SW提前终止 event.waitUntil( clonedResponse.json().then(data => { // 等待所有写入操作全部完成 return Promise.all(Object.values(data).map(item => { return db.then(dbIncidents => { const tx = dbIncidents.transaction('incidents', 'readwrite'); tx.objectStore('incidents').put(item); return tx.done; }) })) }) ) return res; }) ) }
- 事务无错误捕获导致静默失败
你当前的代码没有对IndexedDB事务添加错误捕获逻辑,写入过程中如果出现主键冲突、存储配额不足、对象存储名不匹配等问题,都会直接静默失败不会在控制台抛出报错。你可以给事务添加catch逻辑排查具体错误:
db.then(dbIncidents => { const tx = dbIncidents.transaction('incidents', 'readwrite'); tx.objectStore('incidents').put(data[key]); return tx.done; }).catch(err => console.error('写入失败错误信息:', err))
- 循环创建事务的冲突风险
你当前的代码在循环内每次写入都单独开启一个事务,大量并发事务可能出现排队甚至死锁,建议把所有写入操作放到同一个事务中处理,既提升性能也避免冲突:
clonedResponse.json().then(data => { return db.then(dbIncidents => { const tx = dbIncidents.transaction('incidents', 'readwrite'); const store = tx.objectStore('incidents'); Object.values(data).forEach(item => store.put(item)); return tx.done; }) })
- 冗余索引的潜在兼容问题
你创建对象存储时已经指定keyPath: 'id',id本身就是主键自带原生索引,额外再创建同名的id索引属于冗余配置,部分浏览器的IndexedDB实现可能对同名索引存在兼容问题,建议删除store.createIndex('id', 'id')这行代码。
内容的提问来源于stack exchange,提问作者student
相关产品推荐
相关产品推荐

