2013-06-13 17 views
0

我正在使用Jquery承诺处理打开一个indexedDB来存储文件,然后读写文件(第一次使用这些文件)。由于任何功能可以以任意顺序叫我总是调用该函数试图在手术前先打开数据库,代码如下,如何用jquery promise打开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打开”是每次调用任何函数时都会显示。有没有更好的方法来确保它只被打开一次,然后才能解决接下来的电话?

回答

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) { 
0

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

+0

嗯......在这种情况下,达到这个目标的最佳方法是什么? – Bootstrapper

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

希望你喜欢它!