你如何让 indexeddb 事务保持活跃?

Posted

技术标签:

【中文标题】你如何让 indexeddb 事务保持活跃?【英文标题】:How do you keep an indexeddb transaction alive? 【发布时间】:2012-05-10 06:02:44 【问题描述】:

只要您使用适当的 IDBTransaction,是否可以从单个事务中完成所有这些操作,而不是打开多个事务(读取表、写入表、写入另一个表等)?

Mozilla 说:“保持事务活跃的唯一方法是对其发出请求。当请求完成时,您将收到一个 DOM 事件,假设请求成功,您将有另一个机会在回调期间延长交易。”这有点模糊。这是否意味着如果我为 DOM 回调提供了一个事件处理程序,我可以在该回调的任何时候使用该事务,而不必担心事务被关闭?

https://developer.mozilla.org/en/IndexedDB/Using_IndexedDB#Adding_data_to_the_database

【问题讨论】:

【参考方案1】:

要保持事务处于活动状态,请从完成操作的回调中继续执行下一个操作。请参考以下示例代码。

function put_data(db,tableName,data_array)

    var objectStore=db.transaction([tableName],"readwrite").objectStore(tableName);
    put_record(data_array,objectStore,num_rows,0);


function put_record(data_array,objectStore,row_index)

    if(row_index<data_array.length)
    
        var req=objectStore.put(data_array[row_index]);
        req.onsuccess=function(e)
        
            row_index+=1;
            put_record(data_array,objectStore,row_index);
        ;
        req.onerror = function()
        
            console.error("error", this.error);
            row_index+=1;
            put_record(data_array,objectStore,row_index);
        ;
    

【讨论】:

【参考方案2】:

简短回答:不要保留。

为了防止竞争条件,IndexedDB 是为隐式提交而设计的,因此您不能显式地保持事务处于活动状态。如果需要,请更改您的算法,使其不需要保持活动状态。

重用事务以提高性能并执行有序请求。在这些情况下,事务将隐式保持活动状态。

【讨论】:

【参考方案3】:

简短回答:如果您为“成功”或“错误”事件提供事件处理程序,您可以在该事件处理程序中放置一个新请求,而不必担心事务会自动关闭。

长答案:事务提交通常应该是完全透明的。唯一的规则是你不能在做非数据库“东西”时保持事务打开。 IE。您不能启动事务,然后在执行一些 XMLHttpRequest 或等待用户单击按钮时将其保持打开状态。

一旦您停止对事务提出请求并且最后一个请求回调完成,事务就会自动关闭。

但是您可以启动一个事务,使用该事务读取一些数据,然后写入一些结果。

因此,请确保在开始事务之前拥有所需的所有数据,然后在请求回调中执行您想要执行的所有读取和写入操作。完成后,交易将自动完成。

【讨论】:

感谢您的参与 - 有一位 IDB 规范编写者在附近闲逛真是太棒了 在我的情况下,将一大堆数据从 websqldb 迁移到 indexeddb,这意味着我必须在开始使用 IndexedDB 保存之前将所有这些数据(可能很多兆)保存在内存中?太糟糕了。 关于成功回调返回后的自动提交,如果您从成功回调中将新的 IDB 请求排入事件循环而不是同步放置新请求,会发生什么情况?在这种情况下,第一个成功回调会立即返回,但已经安排了另一个 IDB 请求。 如果你能看看我问的关于交易行为的问题***.com/questions/27326698/…,我会很高兴【参考方案4】:

IndexedDB 事务在最后一个回调被触发后立即提交,因此保持它们活跃的方法是通过回调传递它们。

我的交易信息来自 Jonas Sicking,他是 Mozilla 开发人员和 IndexedDB 的共同规范作者,他在 this excellent blog post 上发表了以下评论:

以下句子不正确“今日交易自动提交 当事务变量超出范围并且没有更多请求时 可以靠它放置”。

当变量用完时,事务永远不会自动提交 范围。通常他们只在最后一次成功/错误回调时提交 触发并且该回调不再安排请求。所以不是 与任何变量的范围有关。

唯一的例外是如果您创建了一个事务但没有放置 反对它的请求。在这种情况下,事务“已提交” (无论这对于没有请求的交易意味着什么)尽快 当您返回事件循环时。在这种情况下,您可以 在技​​术上“提交”交易,只要所有提及它 超出范围,但这不是一个特别有趣的用例 优化。

【讨论】:

最后一段是否意味着如果您创建 ReadWrite 事务,则在创建新的 ReadWrite 事务之前,您不会对其发出任何请求并且不返回事件循环,那么基本上您将获得潜在的死锁/无限作家饥饿。 另一个有趣的问题。关于成功回调返回后的自动提交,如果您从成功回调中将新的 IDB 请求排入事件循环而不是同步放置新请求,会发生什么情况?在这种情况下,第一个成功回调会立即返回,但已经安排了另一个 IDB 请求。 我问了一个新问题,请你看看好吗? ***.com/questions/27326698/… 我喜欢你的规范!如果你对我的库有改进,请在 Github github.com/buley/dash/issues 上打开一个问题我一直在做 IDB,你会讨厌这个建议,但是:阅读规范,但相信你的眼球。给规范一个研究和工程师,但这些事情在实践中有点奇怪,花时间只研究规范有时会适得其反,让你的最终目标发挥作用

以上是关于你如何让 indexeddb 事务保持活跃?的主要内容,如果未能解决你的问题,请参考以下文章

让 WebSocket 在 Mobile Safari 中保持活跃

Apple Watch 让应用程序保持活跃几秒钟

我们怎样才能让 iPhone 屏幕保持活跃,而不是进入省电模式?

IndexedDB - 布尔索引

让会话无限期地保持活跃状态

填充许多 ObjectStore 时的 IndexedDB,错误:无法在“IDBDatabase”上执行“事务”:版本更改事务正在运行