【问题标题】:Howto open IndexedDB just once with jquery promise如何使用 jquery promise 只打开一次 IndexedDB
【发布时间】:2023-03-15 03:21:01
【问题描述】:

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

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

【问题讨论】:

    标签: javascript jquery indexeddb promise


    【解决方案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) {
    

    【讨论】:

      【解决方案2】:

      我已经写了一个小的 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)
      });
      

      希望你喜欢!

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 嗯...在这种情况下实现这一目标的最佳方法是什么?
        猜你喜欢
        • 1970-01-01
        • 2010-12-14
        • 1970-01-01
        • 2020-10-23
        • 2014-02-26
        • 2021-06-30
        • 1970-01-01
        • 1970-01-01
        • 2020-08-11
        相关资源
        最近更新 更多