将许多项目添加到 indexedDB
Adding many items to indexedDB
我正在寻找将许多项目添加到 indexedDB 的最佳实践。 item个数上限一般在100k左右,每个item是一个js对象一般350字节左右
我维护了一个要在数据库上执行的待处理项目(操作)列表(每个操作是 "add"、"put" 或 "delete"),并且每个项目都可以属于不同的对象存储。
我只是获取第一个项目,将其应用到适当的 objectStore,完成后(无论成功与否),我继续进行下一个项目。
有没有更好(更有效)的方法来做到这一点?是否存在任何范围界定问题 w.r.t。我需要在下面的代码片段中关注交易生命周期?
function flushPendingDbActions() {
var transaction = db.transaction(storeNames, "readwrite");
var addNext = function() {
var nextItem = pendingDbActions[0];
if (nextItem) {
pendingDbActions.shift();
var objectStore = transaction.objectStore(nextItem.store),
params,
request;
switch(nextItem.action) {
case 'add':
case 'put':
params = nextItem;
break;
case 'delete':
params = nextItem.key;
break;
}
request = objectStore[nextItem.action](params);
request.onsuccess = request.onerror = addNext;
}
};
addNext();
}
我觉得还不错,但有几点:
- 我会在出现错误时停止正向迭代。错误事件有时表明确实有问题,并且该事务的所有后续请求也可能会失败,并且通过继续错误路径,您只会导致更多错误,其中 N 是剩余的数字。
- 我会使用堆栈或后进先出访问模式。将项目附加到数组上,然后将它们弹出以前进。避免像访问一样使用 shift 和 fifo-queue,这在 js 中的性能很差,因为 shift 比 pop 做的工作多得多。这当然是吹毛求疵,但你问的是效率。有点只在处理大 N 时才重要。
- 根据项目的数量,您可以 运行 进入堆栈溢出类错误,因为每个请求都是所谓堆栈上的待处理函数,从您的代码看起来它累积无界.在这种情况下,您可能希望将请求分批处理成 100 或 1000 之类的块,以避免出现该问题,但这仅在您甚至超过阈值以及代码为 [=34 的特定平台时才重要=]ning(例如在移动设备上可能 运行 遇到麻烦)。
- 还有一个更微妙的异步问题。现在您正在等待每个请求完成,然后再发出下一个请求。为什么?如果请求在逻辑上是独立的,则立即将它们全部关闭,并等待事务完成(只要最后一个挂起的请求完成,事务就会完成)。您通常只需要使用您现在使用的模式,如果每个后续请求的逻辑根据先前的请求发生变化,则每个操作都会等待所有先前的操作完成。所以你在需要none的地方引入了空闲,并且基本上无缘无故地限制自己的速度,同样,前提是请求是独立的。
编辑 - 添加内容:
根据https://www.w3.org/TR/IndexedDB-2/#transaction-lifetime-concept:
Unless otherwise defined, requests must be executed in the order in which they were made against the transaction. Likewise, their results must be returned in the order the requests were placed against a specific transaction.
因此,您应该能够同时发出请求而不是连续发出请求,这应该可以避免 TransactionInactiveError。即使您发出相当于 add item > delete item
.
的请求也是如此
然后你 运行 进入堆栈溢出问题,因为请求位于堆栈中,所以有太多未决请求,然后你应该考虑在这种情况下进行缓冲。因此,获取 pendingactions 数组并将其分块处理。假设一次 1000,将 1000 传递给 processchunk 辅助函数,该函数会触发 1000 个并发请求,等待它完成,然后处理下一个块,直到处理完所有块。
我正在寻找将许多项目添加到 indexedDB 的最佳实践。 item个数上限一般在100k左右,每个item是一个js对象一般350字节左右
我维护了一个要在数据库上执行的待处理项目(操作)列表(每个操作是 "add"、"put" 或 "delete"),并且每个项目都可以属于不同的对象存储。
我只是获取第一个项目,将其应用到适当的 objectStore,完成后(无论成功与否),我继续进行下一个项目。
有没有更好(更有效)的方法来做到这一点?是否存在任何范围界定问题 w.r.t。我需要在下面的代码片段中关注交易生命周期?
function flushPendingDbActions() {
var transaction = db.transaction(storeNames, "readwrite");
var addNext = function() {
var nextItem = pendingDbActions[0];
if (nextItem) {
pendingDbActions.shift();
var objectStore = transaction.objectStore(nextItem.store),
params,
request;
switch(nextItem.action) {
case 'add':
case 'put':
params = nextItem;
break;
case 'delete':
params = nextItem.key;
break;
}
request = objectStore[nextItem.action](params);
request.onsuccess = request.onerror = addNext;
}
};
addNext();
}
我觉得还不错,但有几点:
- 我会在出现错误时停止正向迭代。错误事件有时表明确实有问题,并且该事务的所有后续请求也可能会失败,并且通过继续错误路径,您只会导致更多错误,其中 N 是剩余的数字。
- 我会使用堆栈或后进先出访问模式。将项目附加到数组上,然后将它们弹出以前进。避免像访问一样使用 shift 和 fifo-queue,这在 js 中的性能很差,因为 shift 比 pop 做的工作多得多。这当然是吹毛求疵,但你问的是效率。有点只在处理大 N 时才重要。
- 根据项目的数量,您可以 运行 进入堆栈溢出类错误,因为每个请求都是所谓堆栈上的待处理函数,从您的代码看起来它累积无界.在这种情况下,您可能希望将请求分批处理成 100 或 1000 之类的块,以避免出现该问题,但这仅在您甚至超过阈值以及代码为 [=34 的特定平台时才重要=]ning(例如在移动设备上可能 运行 遇到麻烦)。
- 还有一个更微妙的异步问题。现在您正在等待每个请求完成,然后再发出下一个请求。为什么?如果请求在逻辑上是独立的,则立即将它们全部关闭,并等待事务完成(只要最后一个挂起的请求完成,事务就会完成)。您通常只需要使用您现在使用的模式,如果每个后续请求的逻辑根据先前的请求发生变化,则每个操作都会等待所有先前的操作完成。所以你在需要none的地方引入了空闲,并且基本上无缘无故地限制自己的速度,同样,前提是请求是独立的。
编辑 - 添加内容:
根据https://www.w3.org/TR/IndexedDB-2/#transaction-lifetime-concept:
Unless otherwise defined, requests must be executed in the order in which they were made against the transaction. Likewise, their results must be returned in the order the requests were placed against a specific transaction.
因此,您应该能够同时发出请求而不是连续发出请求,这应该可以避免 TransactionInactiveError。即使您发出相当于 add item > delete item
.
然后你 运行 进入堆栈溢出问题,因为请求位于堆栈中,所以有太多未决请求,然后你应该考虑在这种情况下进行缓冲。因此,获取 pendingactions 数组并将其分块处理。假设一次 1000,将 1000 传递给 processchunk 辅助函数,该函数会触发 1000 个并发请求,等待它完成,然后处理下一个块,直到处理完所有块。