indexeddb 游标中的异步操作
Async operations inside indexeddb cursor
我正在使用 indexedDB Promised 库将 indexedDB API 转换为 promises。
看起来当我的提取完成时,我的索引数据库事务不再处于活动状态。我猜它超时了?
我得到的错误是:
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);
});
});
您不能在 indexedDB 操作的中间进行异步操作。如果 IDBTransaction 在到达 JavaScript 事件循环的当前迭代结束时未检测到任何待处理请求,则它会自动超时。异步操作引入了暂停,因此在暂停之后绑定的后续请求绑定为时已晚,因为到那时事务已超时并结束。事务的生命期很短,因为读写模式事务可能会在整个持续时间内锁定对象存储,从而导致严重的阻塞问题。
要解决此问题,请在事务之前或之后完成所有异步工作,而不是在事务中间。或者使用两个单独的事务,如果数据完整性不是问题的话。
我正在使用 indexedDB Promised 库将 indexedDB API 转换为 promises。
看起来当我的提取完成时,我的索引数据库事务不再处于活动状态。我猜它超时了?
我得到的错误是:
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);
});
});
您不能在 indexedDB 操作的中间进行异步操作。如果 IDBTransaction 在到达 JavaScript 事件循环的当前迭代结束时未检测到任何待处理请求,则它会自动超时。异步操作引入了暂停,因此在暂停之后绑定的后续请求绑定为时已晚,因为到那时事务已超时并结束。事务的生命期很短,因为读写模式事务可能会在整个持续时间内锁定对象存储,从而导致严重的阻塞问题。
要解决此问题,请在事务之前或之后完成所有异步工作,而不是在事务中间。或者使用两个单独的事务,如果数据完整性不是问题的话。