Skip to content

事务作用域与提交 ​

IndexedDB 的写请求完成,不等于事务已经持久化。只有 transaction.oncomplete 触发后,才可以把本次写入当作 durable 成功。

最小实验:等待事务提交 ​

html
<pre id="log"></pre>
<script>
  const log = (value) => document.querySelector('#log').textContent += value + '\n'
  const request = indexedDB.open('lesson-idb', 1)
  request.onupgradeneeded = () => request.result.createObjectStore('items', { keyPath: 'id' })
  request.onerror = () => log(`open error: ${request.error.name}`)
  request.onsuccess = () => {
    const db = request.result
    const tx = db.transaction('items', 'readwrite')
    tx.objectStore('items').put({ id: 1, text: 'saved' })
    tx.oncomplete = () => { log('commit complete'); db.close() }
    tx.onerror = () => log(`transaction error: ${tx.error?.name ?? 'unknown'}`)
    tx.onabort = () => log('transaction aborted')
  }
</script>

第一次运行应输出 commit complete。把 put 改成缺少 id 的对象,观察事务进入错误或中止;刷新后重新打开数据库,确认只有提交成功的数据可读。

机制与边界 ​

事务只在自己的作用域和活动时段内有效。不要把事务对象跨越异步空闲随意保存;需要多个写入时,在同一事务中安排请求,并以 oncomplete 作为整体成功信号。版本升级期间还要处理其他标签页阻塞,否则新 schema 无法切换。

练习 ​

  1. 在同一事务中写入两条记录,让第二条故意违反约束,验证第一条也不会部分提交。
  2. 添加读取事务,比较 onsuccess 与 oncomplete 的含义。
  3. 打开两个标签页测试版本升级,记录 onblocked 并设计提示用户关闭旧页面的恢复路径。

查看本节答案

用心记录每一步成长