angular-ui 中的 $q.all 模态控制器在连续 open/closes 后提前解析

$q.all in angular-ui modal controller resolving early after consecutive open/closes

我目前有一个模态 (Angular-UI 模态),第一次打开时,它可以完美运行。然而,在我关闭它然后重新打开它之后,事情开始变得有点奇怪。

代码:

(function () {
    'use strict';

    angular.module('app.modals').controller('personalizeNewsSubscriptionsModalCtrl', ['$scope', '$log', '$modalInstance', '$q', 'termStoreSvc', 'userNewsSubscriptionsSvc',
            function ($scope, $log, $modalInstance, $q, termStore, userSub) {
                //#region Variable declaration
                var allTopics = [],
                    userSubs = [],
                    subscriptions = new termStore('Manaaged Metadata Service', 'TS Today', 'Topic'),
                    userSubscriptions = new userSub('blackba');

                var allSubsLoaded = subscriptions.ready(function () {
                        allTopics = subscriptions.terms;
                    }),
                    userSubsLoaded = userSubscriptions.ready(function () {
                        userSubs = userSubscriptions.subscriptions;
                    });

                $log = $log.getInstance('app.modals.personalizeNewsSubscriptionsModalCtrl');
                //#endregion                

                $q.all([allSubsLoaded, userSubsLoaded]).then(function () {
                    // use allTopics and userSubs to create $scope.subscriptions
                    $scope.subscriptions = allTopics.map(function (obj) {
                        return {
                            Title: obj,
                            Selected: userSubs.indexOf(obj) !== -1
                        }
                    });
                    $log.debug('Subscriptions object loaded', $scope.subscriptions);
                });

                subscriptions.init();
                userSubscriptions.init();                

                $scope.close = function () {
                    $modalInstance.dismiss('cancel');
                }
            }]);
})();

allSubsLoadeduserSubsLoaded 对象是承诺。要了解这些问题是如何解决的,这里是我的服务的简化版本

(function () {
    'use strict';

    angular.module('app.services.sharepoint')
        .factory('termStoreSvc', ['$log', '$q', function ($log, $q) {
            var self = undefined,
                deferred = $q.defer(),
                promise = deferred.promise;

            var termStoreSvc = function () {                
                self = this;

                self.init = init;
                self.ready = function (fn) {
                    return promise.then(fn);
                }
            };            

            function init() {
                $log.debug('Initializing');

                // do some stuff here                

                $log.debug('Initialized');
                deferred.resolve();
            };


            return termStoreSvc;
        }]);
})();

当我调用 init 时,它会做一些事情,然后解决我声明的隐藏承诺,所以当 ready() 与回调函数一起使用时,回调不会执行,直到 init()方法完成。

出于某种原因,在我第一次 open/close 并打开它 second/third/etc... 时间后,$q.all({array of promises}) 正在提前解决。有什么想法吗?

解决方案的代码示例:

问题是我从工厂返回的对象上没有 promise 和 deferred 对象,这意味着它们是持久化的(所以在第一次之后它们仍然显示为已解决,导致我的 $q.all() 完成 "early").

(function () {
    'use strict';

    angular.module('app.services.sharepoint')
        .factory('termStoreSvc', ['$log', '$q', function ($log, $q) {
            var self = undefined;

            var termStoreSvc = function () {                
                self = this;

                self.init = init;

                self.deferred = $q.defer();
                self.promise = self.deferred.promise;
                self.ready = function (fn) {
                    return self.promise.then(fn);
                }
            };            

            function init() {
                $log.debug('Initializing');

                // do some stuff here                

                $log.debug('Initialized');
                self.deferred.resolve();
            };


            return termStoreSvc;
        }]);
})();

好吧,在我看来,工厂意味着 return 对象,这些对象可能具有作为属性的功能,而且我从未创建过工厂的新实例(新的 termStore 东西)。就像你在第一次已经解决的内存堆栈上做出承诺。单例模式可能会干扰您的意图。

Angular 工厂是单例。工厂定义本身中声明的任何内容都将在程序的生命周期内实例化一次。当然,在对象中声明工厂 returns 的任何内容都会在您每次 new 从中实例化时实例化。 在您的情况下,在工厂定义中声明了一个承诺,并且工厂创建的每个实例都引用了相同的承诺。因此,除了第一个实例之外,您的承诺已经在所有实例中得到解决。