服务/控制器与服务属性上定义的$ watch交互。手表不开火,任何人都可以澄清

时间:2014-05-16 16:00:48

标签: angularjs

我创建了一个服务,它基本上创建了一个间隔,最终会向webapi发送$ http帖子来检索消息。现在我只是将一个新的消息对象添加到数组中进行测试。

在控制器端,我初始化服务并将监视放在其中一个服务属性上,这个想法是当服务添加新消息时我将观察以向用户显示通知。显然,这不会在每次调用时向displayedNotifications数组添加新消息,但这只是测试原型。

以下是我的服务。

(function () {
    'use strict';

    var serviceId = "notificationService";

    //angular.module('app').factory(serviceId, ['helpersService', '$interval', function (helpersService, $interval) {
    angular.module('app').factory(serviceId, ['helpersService', '$interval', function (helpersService, $interval) {
        var defaultOptions = {
            url: undefined,
            interval: 1000
        };

        var myIntervalPromise = undefined;
        var displayedNotifications = [];

        //function onNotificationSuccess(response) {
        //    alert("in success");
        //    return response.data;
        //}

        //function onNotificationFailed(response) {
        //    alert("in Failure");
        //    throw response.data || 'An error occurred while attempting to process request';
        //}


        function initializeNotificationService(configOptions) {

            var passedOptions = $.extend({}, defaultOptions, configOptions);

            if (passedOptions.url) {

                myIntervalPromise = $interval(
                    function() {
                        console.log(passedOptions.url);
                        // eventually this push will accept a string/object returned from a webapi call
                        displayedNotifications.push({ messageobject: "this is new message" });
                    }, passedOptions.interval);

                //alert("in initializeNotificationService");
                return myIntervalPromise;
            }
            return myIntervalPromise;
        }

        //$scope.$on('$destroy', function() {
        //    if (angular.isDefined(myIntervalPromise)) {
        //        $interval.cancel(myIntervalPromise);
        //        myIntervalPromise = undefined;
        //    }
        //});

        return {
            // methods
            initializeNotificationService: initializeNotificationService,
            //properties
            displayedNotifications : displayedNotifications
        };
    }]);

})();

以下是我的控制器

(function () {
'use strict';

var controllerId = 'MessageCtrl';

angular.module('app').controller(controllerId, ['notificationService', '$scope', 

function (notificationService, $scope) {
        var vm = this;
        //vm.notifications = [];

        vm.initialize = function () {
            // initialize tyhe notification service here
            notificationService.initializeNotificationService({url:'this is a test url', interval: 5000})
                .then(
                    function (response) {
                        vm.notifications.push(response);
                         alert("successful call");
                    },
                    function(response) {
                         alert("failure to call");
                    },
                    function(iteration) {
                        // **a break point here clearly shows this property being changed**
                        console.log(notificationService.displayedNotifications);
                        //NEW EDIT HERE
                        $scope.notifications = notificationService.displayedNotifications;
                    }
                );

            $scope.$watch('notifications ', function (newValues, oldValues) {
                alert("watcher notified that notifications have changed");
            }, true);
        };

        vm.alertClicked = function (alert) {
            alert.status = 'old';
        };

        // call to init the notification service here so when the controller is loaded the service is initialized
        vm.initialize();

    }]);
})();

我希望将新消息对象添加到服务的displayNotifications属性时,每隔5秒就会触发watch函数中的警报。然而,它只会在所有内容初始化时触发,然后再不会。我做错了什么?

新编辑

更改了控制器中'.then'的通知功能,将displayNotifications的值分配给$scope.notifications并将监视设置为该变量并且有效。但是,据说在$ scope级别设置一个变量似乎很糟糕...有没有办法在控制器上观察变量,例如vm.notifications =[];的注释行???

1 个答案:

答案 0 :(得分:1)

notificationService.displayedNotifications不在范围内。毕竟你打电话给**$scope**.$watch

您可以将服务或仅属性添加到范围:

$scope.displayedNotifications = notificationService.displayedNotifications;
$scope.watch('displayedNotifications', ...

在您的情况下,示波器上没有notificationService.displayedNotifications,因此无法更改。这就是函数只运行一次的原因。

另一种选择是使用函数作为监视表达式:

$scope.$watch(function() {
    return notificationService.displayedNotifications.length;
  }, function (newValues, oldValues) {

Angular检查函数的返回值是否已更改。

作为@ShawnC。提到你也可以使用事件。在您的服务中,您通过$rootScope.$broadcast发送一个,并在控制器中通过$scope.$on收到它(我不会在控制器中使用$rootScope。)

我能想到的最后一个选择是在你的回调中处理它。无论如何它们都被召唤,所以手表是一种开销。