我有一个使用IndexedDB的应用程序。最初我大量使用了回调,并决定使用angularjs promises $q
来清理它。
FAIL。
http://jsfiddle.net/ed4becky/bumm337e/
angular.module("IDBTest", []);
angular.module("IDBTest")
.service("initSvc", ['$q', function ($q) {
var svc = this;
svc.dbVersion = 1;
svc.open = open;
svc.deleteDB = deleteDB;
var idb = window.indexedDB;
function deleteDB() {
return $q(function (resolve, reject) {
idb.webkitGetDatabaseNames().onsuccess =
function (sender, args) {
if (sender.target.result
&& sender.target.result.length > 0) {
var db = sender.target.result[0];
console.log("deleting " + db);
var request = idb.deleteDatabase(db);
request.onsuccess = function () {
console.log('database ' + db + ' deleted.');
resolve();
};
request.onerror = function () {
reject();
};
} else {
console.log("Nothing to delete");
resolve();
};
};
});
}
function open(dbName) {
return $q(function (resolve, reject) {
var request = idb.open(dbName, svc.dbVersion);
request.onupgradeneeded = function (e) {
var db = e.target.result;
console.log("creating new " + db.name);
e.target.transaction.onerror = function (e) {
console.log(e);
};
db.createObjectStore("table1", {
keyPath: "id"
});
db.createObjectStore("table2", {
keyPath: "id"
});
db.createObjectStore("table3", {
keyPath: "id"
});
};
request.onsuccess = function (e) {
console.log('database ' + dbName + ' open.');
svc.db = e.target.result;
resolve();
};
request.onerror = function () {
reject();
};
});
}
}]);
angular.module('IDBTest')
.factory('$exceptionHandler', ['$log', function ($log) {
return function (exception, cause) {
throw exception;
};
}]);
angular.module('IDBTest')
.run(['initSvc', function (initSvc) {
initSvc.deleteDB()
.then(initSvc.open('testDatabase'))
.then(function () {
console.log(initSvc.db.name + ' initialized');
});
}]);
这个小提琴显示了我的期望
不幸的是,在IDB调用的onsuccess方法中解析了promises之前,then
语句似乎被调用了。
要重新创建,请在控制台打开的情况下运行jsfiddle。可能必须运行它几次才能获得异常,但是大多数时候都会失败,因为在调用数据库打开的onsuccess之前调用last then子句。
有什么想法吗?
答案 0 :(得分:2)
我认为问题在于Promise Chain。来自Angular的文档有点令人困惑,但似乎如果回调方法的返回值是一个promise,它将使用一个值来解析;不是承诺。因此,打破了链条。
来自Angular Promise 'Then' Method Documentation:
then(successCallback, errorCallback, notifyCallback)
- 无论如何 当承诺已经或将要解决或拒绝时,请拨打一个 成功或错误回调一旦结果异步 是可用的。使用单个参数调用回调: 结果或拒绝原因。另外,通知回调可能是 在之前调用零次或多次以提供进度指示 承诺得到解决或拒绝。此方法返回通过解析或拒绝的新承诺 successCallback的返回值,errorCallback(除非那个 value是一个promise,在这种情况下,它用值来解析 使用promise chaining)在该承诺中得到解决。它也通知 通过notifyCallback方法的返回值。承诺不能 从notifyCallback方法中解析或拒绝。
我能够用它来初始化它:
angular.module('IDBTest')
.run(['initSvc', function (initSvc) {
initSvc.deleteDB()
.then(function() {
return initSvc.open('testDatabase');
})
.then(function () {
console.log(initSvc.db.name + ' initialized');
});
}]);