【问题标题】:Promises not working for IndexedDB in angularjsPromise 不适用于 angularjs 中的 IndexedDB
【发布时间】:2015-09-21 12:41:24
【问题描述】:

我有一个使用 IndexedDB 的应用程序。最初我大量使用回调,并决定使用 angularjs promises $q 清理它。

失败。

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

这个小提琴显示了我的期望

  1. 创建的所有数据库都将被删除。 那么
  2. 数据库已打开,触发 onupgradeneeded 那么
  3. 数据库被引用

不幸的是,then 状态似乎在 IDB 调用的 onsuccess 方法中解决承诺之前被调用。

要重新创建,请在打开控制台的情况下运行 jsfiddle。可能需要运行几次才能获得异常,但大多数时候它都会失败,因为最后一个 then 子句在调用数据库打开的 onsuccess 之前被调用。

有什么想法吗?

【问题讨论】:

    标签: javascript angularjs indexeddb angular-promise


    【解决方案1】:

    我认为问题出在 Promise Chain 上。 Angular 的文档有点混乱,但似乎回调方法的返回值是一个承诺,它会用一个值解析;不是承诺。因此,打破了链条。

    来自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');
            });
    }]);
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-20
    • 2014-07-01
    • 2018-07-10
    相关资源
    最近更新 更多