IndexedDB: When to close a connection
Asked Answered
A

4

17

I would like to know what the correct place to close a connection to the database is.

Let's say that I have the following piece of code:

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 basically adds a new element into the database. As per my understanding, when the requestAdd event is triggered that doesn't mean necessarily that the transaction has finished. Therefore I am wondering what the best place to call db.close() is. I was closing the connection inside of requestAdd.onsucess, but if an error happens and requestAdd.onerror is triggered instead, the connection might still be opened. I am thinking about adding trans.oncomplete just under request.onerror and close the db connection here which might be a better option. Any inputs will be more than welcome. Thank you.

Allgood answered 21/1, 2016 at 4:46 Comment(0)
R
15

You may wish to explicitly close a connection if you anticipate upgrading your database schema. Here's the scenario:

  1. A user opens your site in one tab (tab #1), and leaves it open.
  2. You push an update to your site, which includes code to upgrade the database schema, increasing the version number.
  3. The same user opens a second tab to your site (tab #2) and it attempts to connect to the database.

If the connection is held open by tab #1, the connection/upgrade attempt by tab #2 will be blocked. Tab #1 will see a "versionchange" event (so it could close on demand); if it doesn't close its connection then tab #2 will see a "blocked" event.

If the connection is not held open by tab #1, then tab #2 will be able to connect and upgrade. If tab #1 then tries (based on user action, etc) to open the database (with an explicit version number) it will fail since it will be using an old version number (since it still has the old code).

Royroyal answered 22/1, 2016 at 0:22 Comment(4)
Hello Joshua, thank you for your response. I am not pushing any updates, but I would like to know what the proper place to close a connection is. If I close the connection on request.onsuccess and the transaction hasn't finsihed yet, what would happen?Allgood
The spec answers this: w3c.github.io/IndexedDB/#dom-idbdatabase-close => w3c.github.io/IndexedDB/… - "Wait for all transactions created using connection to complete. Once they are complete, connection is closed." - so if you call close() in a success handler the transaction will not be aborted.Royroyal
Rare, but for completeness: Experimentally I have found data to not be guaranteed to be persisted to storage unless db.close() is called and I wait for its success. This comment comes from running on a ChromeOs device and pulling power midway through 200 transactions :) . @JoshuaBellAnselmo
More precisely - when "complete" fires on the transaction, chrome guarantees that data has flushed to disk. (Other browsers may not have that guarantee. There's a performance vs. reliability trade-off.) When you call close() the connection waits for all transactions to complete, which is why you observe that. (I'm curious how you "wait for its success" though - there's no event when close is complete. You can poll via trying to start new transactions, I suppose.)Royroyal
J
10

You generally never need to close a connection. You are not creating memory leaks or anything like that. Leaving the connection open does not result in a material performance hit.

I would suggest not worrying about it.

Also, whether you add trans.oncomplete before or after request.onerror is not important. I understand how it can be confusing, but the order in which you bind the listeners is irrelevant (qualified: from within the same function scope).

Janitor answered 21/1, 2016 at 15:4 Comment(6)
Hi Josh, I understand that the order of the listeners is irrelevant. I would like to clarify my question. Would trans.oncomplete take place regardless the request.x event triggered? or trans.oncomplete would be triggered if and only if request.onsuccess happens?Allgood
Also, I need to make sure that all the connections to the db are closed as I am deleting the IndexedDB just before logging out. As per my understanding if there are connections opened, this task will get blocked until all the connections are closed.Allgood
1) trans.oncomplete will always occur. 2) unclear what you mean by logging out, but that doesn't seem like a reason to close 3) review Joshua Bell's response, he is one of the designers of indexedDB, I would always defer to himJanitor
Hello Josh. Thank you for your response. When a specific event happens I want to delete the indexedDB. I need to make sure that all the connections are closed to avoid a blocked status. This is why I am wondering what the best place to perform this operation is. I will call db.close() in trans.oncomplete which seems to be the most suitable place if I am not wrong.Allgood
close can happen the moment the last request has started, even if multiple requests are still running. close just enqueues a close to eventually occur.Janitor
connections should be closed to avoid being blocked onupgradeneededVolplane
O
3

You can call db.close() immediately after creating the transaction

var trans = db.transaction(storeName, "readwrite");
db.close();

and it will close the connection only after the transaction has completed. https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/close says The connection is not actually closed until all transactions created using this connection are complete. No new transactions can be created for this connection once this method is called.

Overbite answered 6/5, 2022 at 21:58 Comment(0)
A
1

If you want to run multiple versions of your app and both access the same database, you might think it's possible to keep connections open to both. This is not possible. You must close the database on one before opening it on another. But one problem is that there is currently no way to know when the database actually closes.

Archivolt answered 13/6, 2018 at 17:29 Comment(1)
Each of my objectStore(Store class wrapper) methods request a new connection to the database, creates a new transaction, performs the operation and calls close() on the connection before the transaction is complete.Beffrey

© 2022 - 2024 — McMap. All rights reserved.