我在多个页面中使用来自RESTful服务的一些数据。 所以我正在使用棱角分明的工厂。因此,我需要从服务器获取一次数据,并且每次我使用该定义的服务获取数据。就像一个全局变量。以下是样本:
var myApp = angular.module('myservices', []);
myApp.factory('myService', function($http) {
$http({method:"GET", url:"/my/url"}).success(function(result){
return result;
});
});
在我的控制器中,我使用此服务:
function myFunction($scope, myService) {
$scope.data = myService;
console.log("data.name"+$scope.data.name);
}
根据我的要求,它对我来说很好。 但问题是,当我在我的网页上重新加载时,服务将再次被调用并请求服务器。如果在某些其他函数执行之间依赖于“已定义的服务”,它会给出错误,如“某事”是未定义的。所以我想在我的脚本中等待服务加载。我怎样才能做到这一点?无论如何在angularjs中有这样做吗?
答案 0 :(得分:146)
您应该使用promise进行异步操作,而不知道何时完成。承诺“代表了一项尚未完成的业务,但预计将在未来完成。” (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)
示例实现如下:
myApp.factory('myService', function($http) {
var getData = function() {
// Angular $http() and then() both return promises themselves
return $http({method:"GET", url:"/my/url"}).then(function(result){
// What we return here is the data that will be accessible
// to us after the promise resolves
return result.data;
});
};
return { getData: getData };
});
function myFunction($scope, myService) {
var myDataPromise = myService.getData();
myDataPromise.then(function(result) {
// this is only run after getData() resolves
$scope.data = result;
console.log("data.name"+$scope.data.name);
});
}
编辑:关于Sujoys评论 我需要做什么才能使myFuction()调用在.then()函数完成执行之前不会返回。 的
function myFunction($scope, myService) {
var myDataPromise = myService.getData();
myDataPromise.then(function(result) {
$scope.data = result;
console.log("data.name"+$scope.data.name);
});
console.log("This will get printed before data.name inside then. And I don't want that.");
}
好吧,我们假设对getData()的调用需要10秒才能完成。如果该函数在那段时间内没有返回任何内容,它将有效地成为正常的同步代码并将挂起浏览器直到它完成。
随着承诺立即返回,浏览器可以在此期间继续使用其他代码。一旦promise解析/失败,就会触发then()调用。因此,这种方式更有意义,即使它可能会使代码流更复杂(毕竟复杂性是异步/并行编程的常见问题!)
答案 1 :(得分:13)
对于刚接触此人的人,您也可以使用回调,例如:
在您的服务中:
.factory('DataHandler',function ($http){
var GetRandomArtists = function(data, callback){
$http.post(URL, data).success(function (response) {
callback(response);
});
}
})
在您的控制器中:
DataHandler.GetRandomArtists(3, function(response){
$scope.data.random_artists = response;
});
答案 2 :(得分:0)
我遇到了同样的问题,如果这些问题对我有效,则没有。这是做了什么工作......
app.factory('myService', function($http) {
var data = function (value) {
return $http.get(value);
}
return { data: data }
});
然后使用它的函数是......
vm.search = function(value) {
var recieved_data = myService.data(value);
recieved_data.then(
function(fulfillment){
vm.tags = fulfillment.data;
}, function(){
console.log("Server did not send tag data.");
});
};
服务不是必要的,但我认为这是一种可扩展性的良好做法。你需要的大部分内容都适用于任何其他内容,特别是在使用API时。无论如何,我希望这是有帮助的。
答案 3 :(得分:0)
仅供参考,这是使用Angularfire所以它可能会因为不同的服务或其他用途而有所不同,但应该解决同样的问题。我有同样的问题,只有最适合我的解决方案是将所有服务/工厂合并到范围内的单一承诺上。在需要加载这些服务/ etc的每个路由/视图上,我将需要加载数据的任何函数放在控制器函数中,即myfunct()和主app.js在auth i put
之后运行myservice.$loaded().then(function() {$rootScope.myservice = myservice;});
在视图中我刚刚做了
ng-if="myservice" ng-init="somevar=myfunct()"
在第一个/父视图元素/包装器中,以便控制器可以运行
中的所有内容myfunct()
无需担心异步承诺/订单/队列问题。我希望能帮助那些遇到同样问题的人。