如何等待,直到响应来自$ http请求,在angularjs?
我在多个页面中使用来自RESTful服务的一些数据。 所以我正在使用angular工厂。 所以,我需要从服务器获取一次数据,并且每次使用该定义的服务获取数据。 就像全局variables一样。 这是样本:
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中做到这一点?
你应该使用承诺asynchronous操作,你不知道什么时候会完成。 承诺“代表尚未完成的行动,但预计在未来”。 ( 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秒钟才能完成。 如果该函数在这段时间内没有返回任何东西,那么它将会变成正常的同步代码,并且会挂起浏览器直到完成。
尽pipe如此,尽pipe如此,浏览器仍然可以继续使用其他代码。 一旦承诺解决/失败,then()调用被触发。 所以这样做更有意义,即使它可能会使你的代码stream更加复杂一些(复杂性毕竟是一般的asynchronous/并行编程问题!)
对于新来的人,你也可以使用callback,例如:
在您的服务中:
.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; });
我有同样的问题,如果这些为我工作,没有一个。 这是什么工作虽然…
app.factory('myService', function($http) { var data = function (value) { return $http.get(value); } return { data: data } });
然后使用它的function是…
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的时候。 无论如何,我希望这是有帮助的。
仅供参考,这是使用Angularfire,所以它可能会有所不同,为不同的服务或其他用途,但应解决同样的问题。 我有这个同样的问题,只有最适合我的解决scheme是将所有服务/工厂结合到一个范围内的单一承诺。 在每个需要这些服务/等待加载的路由/视图我把任何需要加载数据的控制器function,即myfunct()和主要app.js运行后的auth我把
myservice.$loaded().then(function() {$rootScope.myservice = myservice;});
在我看来,我只是做了
ng-if="myservice" ng-init="somevar=myfunct()"
在第一个/父视图元素/包装,所以控制器可以运行里面的一切
myfunct()
无需担心asynchronous承诺/订单/队列问题。 我希望能帮助有同样问题的人。