如何用jquery承诺打开IndexedDB一次

时间:2013-06-13 11:52:56

标签: javascript jquery indexeddb promise

我正在使用Jquery promises来处理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 opened'。有没有更好的方法来确保它只被打开一次然后才解决后续的呼叫?

3 个答案:

答案 0 :(得分:1)

目前,每次调用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()) {

到:

if(!openDbDeferred) {

答案 1 :(得分: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)
});

希望你喜欢它!

答案 2 :(得分:0)

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