【问题标题】:IndexedDB: When to close a connectionIndexedDB:何时关闭连接
【发布时间】:2016-04-27 05:11:11
【问题描述】:

我想知道关闭与数据库的连接的正确位置是什么。

假设我有以下代码:

function addItem(dbName, versionNumber, storeName, element, callback){

   var requestOpenDB = indexedDB.open(dbName, versionNumber); //IDBRequest
   requestOpenDB.onsuccess = function(event){

        //console.log ("requestOpenDB.onsuccess ");
        var db = event.target.result;

        var trans = db.transaction(storeName, "readwrite");
        var store = trans.objectStore(storeName);    
        var requestAdd = store.add(element);

        requestAdd.onsuccess = function(event) {

                    callback("Success");

        };
        requestAdd.onerror = function(event) {

                    callback("Error");       
        };      

    };
    requestOpenDB.onerror = function(event) { 

        console.log ("Error:" +  event.srcElement.error.message);/* handle error */ 
        callback("Error");
    };         
}

addItem 基本上是在数据库中添加一个新元素。根据我的理解,当 requestAdd 事件被触发时,并不一定意味着事务已经完成。因此,我想知道调用 db.close() 的最佳位置是什么。我正在关闭 requestAdd.onsucess 内部的连接,但如果发生错误并触发了 requestAdd.onerror,则连接可能仍会打开。我正在考虑在 request.onerror 下添加 trans.oncomplete 并在此处关闭数据库连接,这可能是一个更好的选择。任何意见都将受到欢迎。谢谢。

【问题讨论】:

    标签: html indexeddb


    【解决方案1】:

    如果您预期升级数据库架构,您可能希望显式关闭连接。这是场景:

    1. 用户在一个标签(标签 #1)中打开您的网站,然后将其保持打开状态。
    2. 您将更新推送到您的网站,其中包括升级数据库架构的代码,从而增加版本号。
    3. 同一用户打开您站点的第二个选项卡(选项卡 #2)并尝试连接到数据库。

    如果选项卡 #1 保持连接打开,则选项卡 #2 的连接/升级尝试将被阻止。 Tab #1 将看到“versionchange”事件(因此它可以按需关闭);如果它没有关闭其连接选项卡 #2 将看到“阻塞”事件。

    如果连接被标签 #1 打开,则标签 #2 将能够连接和升级。如果选项卡 #1 然后尝试(基于用户操作等)打开数据库(带有明确的版本号),它将失败,因为它将使用旧版本号(因为它仍然具有旧代码)。

    【讨论】:

    • 您好 Joshua,感谢您的回复。我没有推送任何更新,但我想知道关闭连接的正确位置是什么。如果我在 request.onsuccess 上关闭连接并且事务尚未完成,会发生什么?
    • 规范回答了这个问题:w3c.github.io/IndexedDB/#dom-idbdatabase-close => w3c.github.io/IndexedDB/… - “等待使用连接创建的所有事务完成。一旦完成,连接就会关闭。” - 因此,如果您在成功处理程序中调用 close(),事务将不会中止。
    • 罕见,但为了完整性:实验上我发现数据不能保证保存到存储中,除非调用 db.close() 并且我等待它的成功。此评论来自在 ChromeOs 设备上运行并在 200 次交易中途拉动电源:)。 @JoshuaBell
    • 更准确地说——当“完成”事务触发时,chrome 保证数据已刷新到磁盘。 (其他浏览器可能没有这种保证。存在性能与可靠性的权衡。)当您调用 close() 时,连接等待所有事务完成,这就是您观察到的原因。 (不过,我很好奇您如何“等待其成功” - 关闭完成后没有任何事件。我想您可以通过尝试启动新事务进行轮询。)
    【解决方案2】:

    您通常不需要关闭连接。您没有创建内存泄漏或类似的东西。让连接保持打开状态不会对性能造成重大影响。

    我建议不要担心。

    另外,在 request.onerror 之前或之后添加 trans.oncomplete 并不重要。我理解这可能会造成混淆,但是绑定侦听器的顺序无关紧要(限定:来自同一函数范围内)。

    【讨论】:

    • 嗨乔希,我知道听众的顺序是无关紧要的。我想澄清我的问题。无论触发 request.x 事件,trans.oncomplete 都会发生吗?当且仅当 request.onsuccess 发生时才会触发 trans.oncomplete 或 trans.oncomplete?
    • 另外,我需要确保与数据库的所有连接都已关闭,因为我在注销之前删除了 IndexedDB。据我了解,如果有连接打开,此任务将被阻止,直到所有连接都关闭。
    • 1) trans.oncomplete 总是会发生。 2) 不清楚注销是什么意思,但这似乎不是关闭的理由 3) 查看 Joshua Bell 的回复,他是 indexedDB 的设计者之一,我会一直听从他的意见
    • 你好乔希。谢谢您的答复。当发生特定事件时,我想删除 indexedDB。我需要确保所有连接都已关闭以避免阻塞状态。这就是为什么我想知道执行此操作的最佳位置是什么。如果我没记错的话,我会在 trans.oncomplete 中调用 db.close() ,这似乎是最合适的地方。
    • 关闭可能会在最后一个请求开始时发生,即使多个请求仍在运行。关闭只是将最终发生的关闭排入队列。
    【解决方案3】:

    如果您想运行多个版本的应用并同时访问同一个数据库,您可能认为可以同时保持对两者的连接。这不可能。您必须先在一个上关闭数据库,然后再在另一个上打开它。但一个问题是目前无法知道数据库何时真正关闭。

    【讨论】:

    • 我的每个objectStore(Store 类包装器) 方法都请求与数据库的新连接、创建新事务、执行操作并在事务完成之前在连接上调用close()
    猜你喜欢
    • 2011-03-18
    • 2019-07-27
    • 2017-04-13
    • 2021-09-26
    • 2018-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    相关资源
    最近更新 更多