Как открыть IndexedDB только один раз с обещанием jquery

Я использую обещания Jquery для обработки открытия indexedDB для хранения файлов, а затем чтения и записи файлов в нее (использую их впервые). Поскольку любую из функций можно вызывать в любом порядке, я всегда вызываю функцию для открытия БД, прежде чем пытаться выполнить операцию, код приведен ниже:

var DatabaseSingleton = (function () {
        var openDbPromise = $.Deferred();
        var openDb = function() {
            var db;
            var request = window.indexedDB.open("myDb", 2);

            request.onerror = function(event) {
                console.error('Error opening indexedDB connection.');
                openDbPromise.reject();
            }
            request.onsuccess = function(event) {
                console.log('db opened', request.result);
                db = request.result;
                db.onerror = function(event) {
                    console.error("Database error: " + event.target.error.name);
                };
                openDbPromise.resolve(db);
            }
            request.onupgradeneeded = function(event) {
                console.log('upgrading the idb', event.target.result);
                db = event.target.result;
                // create a store for the files
                db.createObjectStore("fileInfo", { keyPath: "name" }).createIndex("name", "name", { unique: false });
            };

            return openDbPromise.promise();
        };

    return {
        // retrive a list of all files in the DB
        getFilesList: function() {
            var filesPromise = $.Deferred();
            openDb().then(function(db) {
                            ...
            });
            return filesPromise.promise();
        },

        // retrieve metainfo of the file specified by its fileName
        getFileinfo: function (fileName) {
            var getInfoPromise = $.Deferred();
            openDb().then(function(db) {
                            ...
            });
            return getInfoPromise.promise();
        },
}) ();

Однако при этом я замечаю, что «db open» отображается каждый раз, когда вызывается любая из функций. Есть ли лучший способ убедиться, что он открывается только один раз, а затем просто разрешается для последующих вызовов?


person Bootstrapper    schedule 13.06.2013    source источник


Ответы (3)


Как бы то ни было, var request = window.indexedDB.open("myDb", 2); и т. д. выполняется безоговорочно каждый раз, когда вызывается openDb().

Самый простой подход — ввести пункт if(...){}, чтобы гарантировать, что var request = window.indexedDB.open("myDb", 2); и т. д. будут выполняться только тогда, когда успешный request (и, следовательно, db) не установлен (или не находится в процессе установления).

Попробуй это :

var DatabaseSingleton = (function () {
    var openDbDeferred;
    var openDb = function() {
        if(!openDbDeferred || openDbDeferred.isRejected()) {
            openDbDeferred = $.Deferred();
            var db;
            var request = window.indexedDB.open("myDb", 2);
            request.onsuccess = function(event) {
                console.log('db opened', request.result);
                db = request.result;
                db.onerror = function(event) {
                    console.error("Database error: " + event.target.error.name);
                };
                openDbDeferred.resolve(db);
            };
            request.onerror = function(event) {
                console.error('Error opening indexedDB connection.');
                openDbDeferred.reject();
            };
            request.onupgradeneeded = function(event) {
                console.log('upgrading the idb', event.target.result);
                db = event.target.result;
                // create a store for the files
                db.createObjectStore("fileInfo", { keyPath: "name" }).createIndex("name", "name", { unique: false });
            };
        }
        return openDbDeferred.promise();
    };
    return {
        //retrive a list of all files in the DB
        getFilesList: function() {
            return openDb().then(function(db) {
                ...
            });
        },
        //retrieve metainfo of the file specified by its fileName
        getFileinfo: function(fileName) {
            return openDb().then(function(db) {
                ...
            });
        }
    };
}) ();

Если вы не хотите, чтобы openDb() продолжал попытки после предыдущей неудачи, измените:

if(!openDbDeferred || openDbDeferred.isRejected()) {

to :

if(!openDbDeferred) {
person Beetroot-Beetroot    schedule 13.06.2013

Я написал небольшой плагин jquery (все еще очень альфа), который делает это:

https://github.com/ameyms/jquery-indexeddb

И я попытался сделать API очень простым:

//Define and initialize an IndexedDB ...
var db = $.idb({
                    name:'foobar', 
                    version: 2,
                    drop: stores_to_be_deleted,
                    stores:list_of_stores
                });

// ... Add objects to a store
db.put(items, 'into_store').done(onsuccess);

//.. And delete objects from a store
db.remove('from_store', conditionFunc).done(onremoval);

//.. And not to forget fetching objects from a store
db.select('from_my_store', conditionFunc).done(function (items){

    console.log(items)
});

Надеюсь, вам понравится!

person Amey    schedule 23.09.2013

На практике конструкция ненадежна, потому что вы не можете надежно использовать соединение с базой данных. Он может быть заблокирован в любое время другим соединением. Не закрывая соединение, вы редко обнаружите, что обещание никогда не разрешается из-за состояния гонки между соединениями. С другой стороны, если вы закроете соединение, как потребитель узнает, что соединение закрыто.

person Kyaw Tun    schedule 14.06.2013
comment
Хм... что было бы лучшим способом добиться этого в этом случае? - person Bootstrapper; 17.06.2013