Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/447.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 正在等待函数在Angular JS中完成_Javascript_Angularjs - Fatal编程技术网

Javascript 正在等待函数在Angular JS中完成

Javascript 正在等待函数在Angular JS中完成,javascript,angularjs,Javascript,Angularjs,我有以下情况:当我的应用程序第一次运行时,在.run函数中,我发出一个http请求以获取“监视器”列表。收到后,它将填充服务中的监控器阵列。许多控制器使用此服务共享数据。此服务称为ZMDataModel。ZMDataModel提供了一个名为isMonitorsLoaded()的函数。当返回1时,我知道监视器数组已填充(并且http调用已完成) 现在,我有一个名为Monitors的页面,其控制器是zmApp.MonitorCtrl,如下所示。在这个监视器中,我需要做的基本上是,从一开始,执行相当于

我有以下情况:当我的应用程序第一次运行时,在.run函数中,我发出一个http请求以获取“监视器”列表。收到后,它将填充服务中的监控器阵列。许多控制器使用此服务共享数据。此服务称为ZMDataModel。ZMDataModel提供了一个名为isMonitorsLoaded()的函数。当返回1时,我知道监视器数组已填充(并且http调用已完成)

现在,我有一个名为Monitors的页面,其控制器是zmApp.MonitorCtrl,如下所示。在这个监视器中,我需要做的基本上是,从一开始,执行相当于:

while (ZMData.isMonitorsLoaded()!=1);
现在我显然不能这样做,因为它会锁定我的浏览器,而浏览器从一开始就没有机会将isMonitorLoaded设置为1,所以它变成了一个无休止的循环

我知道我需要以某种方式设置一个超时,但不能完全理解我需要在控制器中执行的操作。我的控制器代码如下:

angular.module('zmApp.controllers').controller('zmApp.MonitorCtrl',函数($scope,$http,ZMHttpFactory,ZMDataModel){
$scope.monitors=[];
日志(“***在我继续之前等待监视器加载”);
//我无法在等待ZMDataModel.isMonitorsLoaded时进行紧密循环
//那么有时间吗?
$scope.monitors=ZMDataModel.getMonitors();
log(“我得到了”+$scope.monitors);
$scope.doRefresh=函数(){
console.log(“***拉刷新”);
$scope.monitors=[];
ZMHttpFactory.getMonitors().then(函数(数据){
$scope.monitors=数据;
$scope.$broadcast('scroll.refreshComplete');
log(“我得到了”+$scope.monitors);
});
};

});
您可以使用
$rootScope.$emit('eventName')
,对于使用
$rootScope.$on('eventName')订阅它们的任何人来说,它的工作方式类似于事件广播:


为什么不使用一个承诺来解决当您的监视器服务器加载时的问题?您可以将服务设置为:

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;

    }
]);
现在,您可以像这样在任何地方使用您的服务:

角度.module('zmApp.controllers').controller('zmApp.MonitorCtrl',['$scope','ZMDataModel',函数($scope,ZMDataModel){


如果其他控制器先加载服务,这并不重要。只要您使用加载函数而不将“刷新”标志设置为true,服务就不会再次加载

出于某种设计原因,服务必须是这样吗?我想知道为什么不使用路由解析加载数据并将其注入控制器John,它不会。我不知道w to AngularJS-你能解释一下如何使用路由解析来加载数据,然后再加载此视图吗?听起来像是我在寻找的东西看这里我有点困惑。我现在理解解析部分。但它要求它所依赖的函数返回一个承诺。我的困境是:ZMDataModel有两个函数类似这样的选项:isMonitorsLoaded:function(){return monitorsLoaded;},setMonitorsLoaded:function(loaded){console.log(“ZMData.setMonitorsLoaded=“+loaded”);monitorsLoaded=loaded;}IsTimeServsAdvices只是返回一个变量。StimeTimeRsS加载在一个不同的工厂被调用时,它的操作完成了。那么我如何让GET FN承诺呢?这里有一些更新的代码。如果你看到日志,这个承诺工作得很好——但是看起来路由解析仍然不是加载控制器。有什么帮助吗?你好,斯特凡,我在中间。尝试构建承诺并将其附加到routes resolve中。如果您有时间,请查看我在上面对John Stewart的回复。如果它不起作用,我将深入研究您的方法。同时,如果您可以查看我的方法可能存在的问题,我将非常感谢(最新的代码片段位于)将states与resolves对象一起使用绝对是个好主意。您仍然可以按照我的建议编写服务。在您的state中,您可以编写:。state('myState',{url:'/monitors',templateUrl:'monitors.html',controller:'monitors controller',resolve:{loadedZMDataModel:['ZMDataModel',function(ZMDataModel){返回ZMDataModel.load();}]})啊,我解决了这个问题。我必须将延迟变量移出函数-现在效果很好。我想之前发生的事情是,它被不同的延迟实例调用。Stefan,谢谢你的关注-我现在也将根据你的建议开始优化它。好的,我把我的状态弄得一团糟。Stefan你的回答e看起来很全面。我明天将重置、重新阅读并查看我的代码,并尝试按照您在上面的答案中的建议进行操作。我将在我完成您的建议时发布后续内容。Tefan,使用MyServices的逻辑是什么?我的ZMDataModel服务中包含多个功能。它的格式为返回{function1:function(){..},function2:function(){..}等};
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;

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

}]);