2013-06-13 3 views
0

Я использую Jquery обещания обрабатывать открытие indexedDB для хранения файлов, а затем читать и писать файлы на него (я использую их в первый раз). Как и любой из функций может быть вызвана в любом порядке, я всегда вызывать функцию, чтобы открыть DB первой перед попыткой операции, код, как показано ниже,Howto open IndexedDB только один раз с jquery обещанием

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

Однако с этим я замечаю «Д.Б. открыл» быть отображается каждый раз, когда вызывается любая из функций. Есть ли лучший способ убедиться, что он только открывается один раз, а затем просто разрешен для последующих вызовов?

ответ

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

Надежда тебе нравится это!