0

我正在使用 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();
        },
}) ();

但是,我注意到每次调用任何函数时都会显示“打开的数据库”。有没有更好的方法来确保它只被打开一次,然后才解决后续调用?

4

3 回答 3

1

就目前而言,var request = window.indexedDB.open("myDb", 2);等每次openDb()被调用时都会无条件地执行。

最直接的方法是引入一个if(...){}子句,以确保var request = window.indexedDB.open("myDb", 2);etc 仅在未建立成功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()) {

到 :

if(!openDbDeferred) {
于 2013-06-13T17:25:27.117 回答
1

我编写了一个小的 jquery 插件(仍然非常 alpha)来执行此操作:

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)
});

希望你喜欢!

于 2013-09-23T08:13:22.327 回答
0

该设计在实践中并不可靠,因为您无法可靠地使用数据库连接。它可以随时被其他连接阻止。在不关闭连接的情况下,您很少会发现,由于连接之间的竞争条件,承诺永远不会解决。另一方面,如果您关闭连接,消费者将如何知道连接已关闭。

于 2013-06-14T03:09:08.083 回答