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