简体   繁体   English

等待功能在Angular JS中完成

[英]Waiting for function to complete in Angular JS

I have the following situation: When my app first runs, in the .run function, I issue an http request to get a list of "monitors". 我遇到以下情况:当我的应用程序首次运行时,在.run函数中,我发出一个http请求以获取“监视器”列表。 Once received, it populates a monitors array in a service. 收到后,它将在服务中填充监视器阵列。 This service is used by many controllers to share data. 许多控制器使用此服务来共享数据。 This service is called ZMDataModel. 该服务称为ZMDataModel。 ZMDataModel offers a function called isMonitorsLoaded(). ZMDataModel提供了一个称为isMonitorsLoaded()的函数。 When this returns 1, I know the monitors array is populated (and that the http call is complete) 当它返回1时,我知道已填充monitors数组(并且http调用已完成)

Now, I have a page called Monitors, the controller for which is zmApp.MonitorCtrl, shown below. 现在,我有一个名为Monitors的页面,其控制器为zmApp.MonitorCtrl,如下所示。 What I need to do, in this MonitorCtrl is to basically, right at the start, do an equivalent of: 我需要做的是,在此MonitorCtrl中,基本上是从一开始就等效于:

while (ZMData.isMonitorsLoaded()!=1);

Now I obviously can't do that because it locks my browser up, and the browser never gets a chance to set isMonitorLoaded to 1 in the first place, so it becomes an endless loop. 现在,我显然无法执行此操作,因为它锁定了我的浏览器,并且浏览器始终没有机会将isMonitorLoaded设置为1,因此它变成了一个无限循环。

I understand I need to put in a timeout somehow, but can't quite follow what I need to do in the controller. 我知道我需要以某种方式设置超时时间,但不能完全遵循我在控制器中需要执行的操作。 My controller code is below: 我的控制器代码如下:

 angular.module('zmApp.controllers').controller('zmApp.MonitorCtrl', function($scope, $http, ZMHttpFactory, ZMDataModel) { $scope.monitors = []; console.log("***Waiting for Monitors to load before I proceed"); // I can't do a tight loop waiting for ZMDataModel.isMonitorsLoaded // so some timeout? $scope.monitors = ZMDataModel.getMonitors(); console.log("I GOT " + $scope.monitors); $scope.doRefresh = function() { console.log("***Pull to Refresh"); $scope.monitors = []; ZMHttpFactory.getMonitors().then(function(data) { $scope.monitors = data; $scope.$broadcast('scroll.refreshComplete'); console.log("I GOT " + $scope.monitors); }); }; }); 

You can use $rootScope.$emit('eventName') which works like a broadcast of events for anyone who is subscribe to them whit $rootScope.$on('eventName') : 您可以使用$rootScope.$emit('eventName') ,它的作用就像广播事件一样,适用于订阅了$rootScope.$on('eventName')

// In your monitor loaded method:
onload: function(){
  //Here you can pass optional information to the listeners
  // for Example an array of monitor or an object
  $rootScope.$emit('MONITORS_LOADED',{
    monitors: getMonitors()   
  });
}

// In your controller:
angular.module('zmApp.controllers').controller('zmApp.MonitorCtrl', function($rootScope, $scope, $http, ZMHttpFactory, ZMDataModel) {

  $scope.monitors = [];

  $rootScope.$on('MONITOR_LOADED', function(event, data) {  
    $scope.monitors = data;
    // or 
    // $scope.monitors = ZMDataModel.getMonitors();

    console.log("I GOT " + $scope.monitors);
}

$scope.doRefresh = function() {
  //...
 });
};

});

Why not using a promise which will resolve when your monitor servers is loaded? 为什么不使用将在加载监视服务器时解决的Promise? You can set up your service as: 您可以将服务设置为:

angular.module('myApp')
    .service ('ZMDataModel', ['$http', function ($http) {

    function MyServices () {
        var _deferred;
        var _isLoading;
        var me = this;

        this.isLoaded = false;

        this.load = function (reload) {

            if (!_deferred || (!_isLoading && reload)) {
                this.isLoaded = false;
                _deferred = $q.defer();

                _isLoading = true;

                // make your call
                $http ({get : 'http://your-site.com'})
                    .then (
                        function success (rawData) {
                            me.isLoaded = true;
                            // parse your data
                            me.monitors = rawData;

                            _deferred.resolve(me);
                        },
                        function fail (error) {
                            _deferred.reject(error);
                            _deferred = null;

                            if (onFail) {
                                me.monitors = [];
                            }
                        }
                    )
                    .finally (
                        function () {
                            _isLoading = false;
                        }
                    );
            }

            return _deferred.promise;
        };
    }

    return MyServices;

    }
]);

Now you can use your service everywhere like this: 现在,您可以像下面这样在任何地方使用服务:

angular.module('zmApp.controllers').controller('zmApp.MonitorCtrl', ['$scope', 'ZMDataModel', function($scope, ZMDataModel) { angular.module('zmApp.controllers')。controller('zmApp.MonitorCtrl',['$ scope','ZMDataModel',function($ scope,ZMDataModel){

    $scope.monitors = [];


    console.log("***Waiting for Monitors to load before I proceed");
    // I can't do a tight loop waiting for ZMDataModel.isMonitorsLoaded
    // so some timeout?

    ZMDataModel.load ().then (
        function (response) {
            $scope.monitors = ZMDataModel.monitors;
        }
    );

    $scope.doRefresh = function() {
        console.log("***Pull to Refresh");
        $scope.monitors = [];
        ZMDataModel.load (true).then (
            function (response) {
                $scope.monitors = ZMDataModel.monitors;
            }
        );
    };

}]);    

It doesn't matter if an other controller loads the service first. 另一个控制器是否首先加载服务并不重要。 As long as you use the load function without the 'refresh' flag set to true, the service won't load again 只要您在不将“ refresh”标志设置为true的情况下使用加载功能,该服务就不会再次加载

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

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