gpt4 book ai didi

javascript - IndexedDB 事务的目的相互冲突

转载 作者:行者123 更新时间:2023-12-03 11:07:10 26 4
gpt4 key购买 nike

据我了解,将多个 IndexedDB 操作放在单个事务中而不是为每个操作使用唯一的事务有三个不同的原因:

  1. 性能。如果您要对对象存储进行大量写入,那么如果这些写入发生在一个事务中,速度会快得多。
  2. 在继续之前确保数据已写入。 Waiting for the “oncomplete” event is the only way to be sure that a subsequent IndexedDB query won’t return stale data.
  3. 执行一组原子数据库操作。基本上,“做所有这些事情,但如果其中一项失败,则将其全部回滚”。

#1 没问题,大多数数据库都有相同的特征。

#2 有点独特,与#3 一起考虑时会引起问题。假设我有一些简单的函数,可以将一些内容写入数据库并在结束时运行回调:

function putWhatever(obj, cb) {
var tx = db.transaction("whatever", "readwrite");
tx.objectStore("whatever").put(obj);
tx.oncomplete = function () { cb(); };
}

效果很好。但现在,如果您想将该函数作为一组操作的一部分来调用,并且希望以原子方式提交或失败,这是不可能的。你必须做这样的事情:

function putWhatever(tx, obj, cb) {
tx.objectStore("whatever").put(obj).onsuccess = function () { cb(); };
}

该函数的第二个版本与第一个版本非常不同,因为回调在保证将数据写入数据库之前运行。如果您尝试读回刚刚写入的对象,您可能会得到一个过时的值。

基本上,问题在于您只能利用#2 或#3 之一。有时选择是明确的,但有时则不然。这导致我编写了可怕的代码,例如:

function putWhatever(tx, obj, cb) {
if (tx === undefined) {
tx = db.transaction("whatever", "readwrite");
tx.objectStore("whatever").put(obj);
tx.oncomplete = function () { cb(); };
} else {
tx.objectStore("whatever").put(obj).onsuccess = function () { cb(); };
}
}

但是,即使这仍然不是通用解决方案,在某些情况下可能会失败。

还有其他人遇到过这个问题吗?你如何解决?或者我只是以某种方式误解了事情?

最佳答案

以下只是意见,因为这似乎不是一个“唯一正确答案”的问题。

首先,性能是一个无关紧要的考虑因素。完全避免这个因素,除非后来的分析表明存在重大问题。出现性能问题的可能性非常低。

其次,我更喜欢将请求组织到事务中,只是为了保持完整性。诚信至关重要。我在这里定义的完整性仅仅意味着数据库在任何一个时间点都不包含冲突或不稳定的数据。本质上,数据库永远无法进入“坏”状态。例如,施加一个规则,即跨存储对象引用指向其他存储中有效且现有的对象(也称为引用完整性),或者防止重复请求,例如双重添加/放置/删除。显然,如果该应用程序类似于贷记/借记帐户的银行应用程序或心脏病发作监控应用程序,那么事情可能会出现严重错误。

我自己的经验让我相信涉及indexedDB的代码不容易出现传统的外观模式。我发现,就将请求组织到不同的包装函数中而言,最有效的方法是围绕事务设计函数。我发现很多时候很少DRY violations因为每个请求对于其事务上下文来说几乎总是唯一的。换句话说,虽然类似的“放置对象”请求可能出现在多个事务中,但鉴于其单独的上下文,其行为是如此不同,以至于值得违反 DRY。

如果您使用每个请求路由的函数,我不确定您为什么要检查事务参数是否未定义。让调用者创建该函数,然后依次将其传递给请求。期望交易始终被定义,并且不要过度热心地防范它。如果它没有被定义,那么在indexedDB或你的调用函数中可能存在严重的错误。

明确地说,类似于:

function doTransaction1(db, onComplete) {
var tx = db.transaction(...);
tx.onComplete = onComplete;
doRequest1(tx);
doRequest2(tx);
doRequest3(tx);
}
function doRequest1(tx) {
var store = tx.objectStore(...);
// ...
}
// ...

如果请求不应并行执行,而必须串行运行,那么这表明存在更大且更困难的设计问题。

关于javascript - IndexedDB 事务的目的相互冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27791057/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com