indexeddb游标中的异步操作

时间:2018-08-17 03:39:17

标签: javascript asynchronous promise indexeddb

我正在使用 indexedDB 应许库将 indexedDB API 转换为Promise。

看起来像我提取完成时,索引数据库事务不再处于活动状态。我猜是超时了吗?

我得到的错误是:

DOMException: Failed to execute 'delete' on 'IDBCursor': The transaction has finished.

仅在且仅当获取成功完成时,我才尝试从indexedDB中删除项目。我了解我可以在提取后创建第二个交易来获取并删除该项目。但是我想知道是否有更好的方法而不进行新交易?我想念什么吗?

有人可以向我解释为什么我遇到这个问题吗?

DBHelper.DBPromised.then( db => {
  const store = db.transaction('deferredReviews', 'readwrite').objectStore('deferredReviews');
  const submittedRes = {};
  store.openCursor()
    .then(function submitAndDelete(cursor) {
        if (!cursor) return;
        console.log(cursor.value);

        fetch(`${DBHelper.DATABASE_URL}/reviews`, {
          method: 'POST',
          body: JSON.stringify({
            restaurant_id: cursor.value.restaurant_id,
            name: cursor.value.name,
            createdAt: cursor.value.deferredAt,
            rating: cursor.value.rating,
            comments: cursor.value.comments
          })
        })
        .then(response => {
          if (!response.ok) {
            throw Error(response.statusText);
          }
          return response.json();
        })
        // If response is ok then delete from indexedDB.
        .then(review => {
          if (!review) return new Error('Could not submit');
          if (cursor.value.restaurant_name in submittedRes) {
            submittedRes[cursor.value.restaurant_name] = submittedRes[cursor.value.restaurant_name] + 1;
          } else {
            submittedRes[cursor.value.restaurant_name] = 1;
          }
          cursor.delete();
          return cursor.continue().then(submitAndDelete);
        });
    })
    .then(() => {
      if (Object.keys(submittedRes).length === 0 && submittedRes.constructor === Object) return;
        DBHelper.showDeferredSubmitModal(submittedRes);
    });
});

1 个答案:

答案 0 :(得分:4)

您不能在indexedDB操作的中间执行异步操作。如果IDBTransaction到达JavaScript事件循环当前迭代的末尾时未检测到任何未决请求,它将自动超时。异步操作会引入一个暂停,因此在暂停之后绑定的后续请求绑定得太晚了,因为到那时事务已超时并结束。事务原本打算是短暂的,因为读写模式事务可能会在整个期间锁定对象存储,从而导致严重的阻塞问题。

要解决此问题,请在事务之前或之后(而不是在事务中间)执行所有异步工作。如果数据完整性不成问题,或者使用两个单独的事务。