繁体   English   中英

如何从AngularJS应用程序的控制器中监视服务中的变量?

[英]How to watch variable in service from controller within AngularJS application?

我正在编写应用程序功能,该功能可以在执行请求时设置加载gif(出于学习目的)。 我使用AngularJS 1.4.5,“ Controller as”语法和John Papa样式指南。 因此,我编写了一个拦截器 ,将当前请求的数量传递给服务:

(function () {
    'use strict';
    angular
        .module('eventApp')
        .factory('requestInterceptorService', requestInterceptorService);

    requestInterceptorService.$inject = ['$q', 'loadingService'];

    function requestInterceptorService($q, loadingService) {

        var numLoadings = 0; 
        var requestInterceptorServiceFactory = {
            request: request,
            response: response,
            responseError: responseError
        };
        return requestInterceptorServiceFactory;

        function request(config) {
            numLoadings++;
            loadingService.setLoaderStatus(numLoadings);
            return config || $q.when(config);
        }
        function response(response) {
            numLoadings--;
            loadingService.setLoaderStatus(numLoadings);
            return response || $q.when(response);

        }
        function responseError(response) {
            numLoadings--;
            loadingService.setLoaderStatus(numLoadings);
            return $q.reject(response);
        }
    }
})();

这是我loading.service与标志isLoadgerEnabled,指示我们是否需要显示加载图像或不:

(function () {
    'use strict';
    angular
        .module('eventApp')
        .factory('loadingService', loadingService);

    function loadingService() {

        var isLoaderEnabled = false;

        var loadingServiceFactory = {
            setLoaderStatus: setLoaderStatus,
            getLoaderStatus: getLoaderStatus,
            isLoaderEnabled: isLoaderEnabled
        };

        return loadingServiceFactory;

        function setLoaderStatus(numberOfRequests) {
            var status = false;
            if (numberOfRequests === 0) {
                status = false;
            }
            if (numberOfRequests !== 0) {
                status = true;
            }
            isLoaderEnabled = status;
        }

        function getLoaderStatus() {
            return isLoaderEnabled;
        }
    }
})();

上面的代码对我有用。 在视图上,我有div,它带有image和ng-show指令 ,它从索引控制器监听标志

<div id="loaderDiv">
   <img src="client/assets/img/loader.gif" class="content-loader" 
        ng-show="index.isLoaderEnabled" />
</div> 

.controller('indexController', indexController);

    indexController.$inject = ['$location', 'authService', 'authModal', 'loadingService', '$scope'];

    function indexController($location, authService, authModal, loadingService, $scope) {
        var vm = this;

        vm.isLoaderEnabled = loadingService.isLoaderEnabled;
        //code with other functionality 

        $scope.$watch(function () {
            return loadingService.isLoaderEnabled;
        }, function (newValue) {
            vm.isLoaderEnabled = newValue;
        });
    }
})();

我的问题:vm.isLoaderEnabled 无法通过服务进行更新 (实际上vm.isLoaderEnabled始终为false),而且我不确定问题出在哪里。 我想为此功能编写高效而优雅的解决方案,也许不用$ scope(如果可能)。 我已经准备好提出问题,重构建议或更好的想法来绑定数据以供查看。

好的,我设法找到解决问题的方法。 首先,我要指向loadingService中的那部分代码:

var loadingServiceFactory = {
            setLoaderStatus: setLoaderStatus,
            getLoaderStatus: getLoaderStatus,
            isLoaderEnabled: isLoaderEnabled//<------1 line
        };

        return loadingServiceFactory;//<------2 line

第一行中 isLoaderEnabled 复制到属性isLoaderEnabled,在第二行中 ,将其返回。 因此,loadingController获取我的加载标志的副本 如果仅发现较早版本的代码可以工作(因为我尝试了许多其他解决方案)。

因此,解决方案。 我使用Observer模式解决了这一问题:在Angular中这不是很好的做法,但是它可以工作(无论如何,以后我会覆盖我的代码)。

  1. requestInterceptor-不变

  2. 加载服务:

      (function () { 'use strict'; angular .module('eventApp') .factory('loadingService', loadingService); function loadingService() { var isLoaderEnabled = false; var callbacks = []; var loadingServiceFactory = { setLoaderStatus: setLoaderStatus, getLoaderStatus: getLoaderStatus, register: register }; return loadingServiceFactory; function setLoaderStatus(numberOfRequests) { if (numberOfRequests === 0) { isLoaderEnabled = false; } if (numberOfRequests > 0) { isLoaderEnabled = true; } notify(); } function getLoaderStatus() { return isLoaderEnabled; } function register(callback) { callbacks.push(callback); } function notify() { callbacks.forEach(function (callback) { callback(); }); } } })(); 
  3. 加载控制器:

     (function () { 'use strict'; angular .module('eventApp') .controller('indexController', indexController); indexController.$inject = ['$location', 'authService', 'authModal', 'loadingService']; function indexController($location, authService, authModal, loadingService) { /* jshint validthis: true*/ var vm = this; vm.loading = false; vm.loaderObserver = function () { vm.loading = loadingService.getLoaderStatus(); } loadingService.register(vm.loaderObserver); //other unnecessary code }; })(); 
  4. 装载机div

      <div id="loaderDiv" ng-show="index.loading" > <img src="client/assets/img/loader.gif" class="content-loader" /> </div> 

我希望这会对某人有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM