我正在使用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'。有没有更好的方法来确保它只被打开一次然后才解决后续的呼叫?
答案 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)
设计在实践中并不健全,因为您无法可靠地使用数据库连接。它可以通过其他连接随时阻止。如果不关闭连接,您很快就会发现,由于连接之间的竞争条件,承诺永远不会解决。另一方面,如果关闭连接,消费者将如何知道连接已关闭。