刚刚开始我的第一个项目 IndexedDb,我很难尝试创建一个在第一次使用时打开和升级数据库的系统。我想使用承诺(当前角Js$q https://code.angularjs.org/1.2.22/docs/api/ng/service/%24q服务,但我很灵活)给我一些关于捕获发生的错误的保证,并减少推理故障模式的精神开销。我的要求是:
- 消费者调用一些函数来打开和升级返回承诺的数据库
- 该功能按顺序执行所有必要的升级/迁移。如果没有发生错误,则通过连接到数据库来解决承诺
- 如果任何阶段发生任何错误,则 Promise 一定会因错误而被拒绝
- 添加新的迁移/升级步骤就像定义执行升级的函数一样简单,所有其他并发问题都由“框架”处理。
到目前为止我遇到的问题:
- The
onupgraderequired
如果数据库不需要升级,则不会调用回调(因此,如果数据库不需要升级,则在升级完成时得到解决的承诺将永远不会得到解决,并且调用代码不知道在以下情况下是否会出现这种情况连接回调)
- 如果一项升级依赖于另一项升级(例如填充您刚刚创建的商店),则必须等到其升级
onsuccess
调用回调 - 因此每次升级都需要顺序链接
- 看起来,在链中的前一个解决之后执行的承诺的延迟足以在再次需要之前将“交易”标记为不活动(我认为它们是用“nextTick”安排的,这可能是相同的机制从而使交易无效)。
-
update如果一个升级依赖于另一个升级,那么到
onsuccess
第一个回调被调用,versionchange
交易不再活跃。
我目前的结论是,API 从根本上反对基于承诺的方法。我最好的尝试如下(为了便于阅读而进行了一些简化)。我哪里错了?
var newPromise = function(withDeferred) {
var deferred = $q.defer();
try {
withDeferred(deferred);
} catch (err) {
deferred.reject(err);
}
return deferred.promise;
};
var newTransactionPromise = function(getTransaction) {
return newPromise(function(deferred) {
var transaction = getTransaction();
transaction.oncomplete = function(ev) { deferred.resolve(); };
transaction.onabort = function(ev) { deferred.reject(transaction.error); };
});
};
var migrations = [
function(db) {
return newTransactionPromise(function() {
// throws: The database is not running a version change transaction.
return db
.createObjectStore("entries", { keyPath: 'id', autoIncrement: true })
.transaction;
});
},
function(db) {
return newTransactionPromise(function()
{
var entryStore = db.transaction("entries", "readwrite").objectStore("entries");
entryStore.add({ description: "First task" });
return entryStore.transaction;
});
}
];
var upgradeAndOpen = function() {
return newPromise(function(deferred) {
var latest_version = migrations.length;
var request = indexedDB.open("caesium", latest_version);
request.onupgradeneeded = function(event) {
try {
// create an already resolved promise to start a chain
var setupDeferred = $q.defer();
setupDeferred.resolve();
var setupComplete = setupDeferred.promise;
for (var v = event.oldVersion; v < latest_version; v++)
{
// Problem: the versionchange transaction will be 'inactive' before this promise is scheduled
var nextMigration = migrations[v].bind(this, request.result);
setupComplete = setupComplete.then(nextMigration);
}
setupComplete["catch"](deferred.reject);
} catch (err) {
deferred.reject(err);
}
};
request.onerror = function(event) { deferred.reject(request.error); };
request.onsuccess = function(event) { deferred.resolve(request.result); };
});
};
upgradeAndOpen()["catch"](function(err) { $scope.status = err; });
var open = function(name, ver) {
return new Promise(function(yes, no) {
var req = indexedDB.open(name, var);
req.onupgradedneeded = function(res) {
no(req);
req.onsuccess = null; // for clarity
};
req.onsuccess = function() {
yes(res.result);
};
req.onblocked = no;
}
});
open('db name', 3).then(function(db) {
// use db here
}, function(req) {
// version upgrade logic here
if (req instanceof IDBResult) {
return new Promise(function(yes, no) {
req.transaction.createObjectStore('store_3');
req.onsuccess = function() {
yes(req.result);
});
});
}
});
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)