0

私は Jquery promises を使用して indexedDB を開いてファイルを保存し、ファイルを読み書きします (これらを初めて使用しています)。どの関数も任意の順序で呼び出すことができるため、操作を試みる前に最初に関数を呼び出して DB を開きます。コードは次のとおりです。

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」が表示されることに気付きます。一度だけ開かれ、その後の呼び出しで解決されるようにするためのより良い方法はありますか?

4

3 に答える 3

1

これを行う小さな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)
});

気に入っていただければ幸いです。

于 2013-09-23T08:13:22.327 に答える
1

このままでは、 etcが呼び出されるvar request = window.indexedDB.open("myDb", 2);たびに無条件に実行されます。openDb()

最も簡単なアプローチは、if(...){}節を導入して、成功した(したがって) が確立されていない (または確立されていない)var request = window.indexedDB.open("myDb", 2);場合にのみ etc が実行されるようにすることです。requestdb

これを試して :

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 に答える
0

データベース接続を確実に使用できないため、設計は実際には堅牢ではありません。他の接続によっていつでもブロックできます。接続を閉じないと、まれに、接続間の競合状態が原因で promise が解決されないことがわかります。一方、接続を閉じた場合、消費者は接続が閉じられたことをどのように知ることができますか。

于 2013-06-14T03:09:08.083 に答える