是否可以使用$ q在AngularJS中同步触发ajax请求?
我有一长串vehicles
,每个vehicle
都有events
与他们相关联,我需要检索每个eventdetails
的{{1}}用户扩展了列表。
现在,如果用户扩展了列表,我会异步拨打15个调用,这似乎导致了我正在消耗的API问题,所以我想看看如果我等待,性能是否会提高每个请求在解雇下一个请求之前完成。
我正在尝试实施event
以延迟下一个请求,直到上一个请求完成,但是我似乎无法使用该服务,这就是我目前所拥有的:
$q
这仍然是异步发射,我在哪里错了?
我理解同步触发请求并不是最好的主意,目前我只想知道API的性能是否有所改善。
答案 0 :(得分:9)
您不需要$q
来实施承诺,因为$http
会返回承诺。
_.each
在没有特别等待承诺的情况下触发所有回调。
只要您的承诺得到解决,您所做的只是致电retrieveData
所有事件,并且由于您没有先拨打电话,它甚至不能正常工作
你可以这样做一些递归调用:
var retrieveEventDetails = function(events) {
var evt = events.shift();
$http({
url: '/api/eventdetails',
method: 'POST',
data: {
event_number: evt.number
},
isArray: true
}).then(function(response){
console.log(response.data);
retrieveEventDetails(events);
});
}
答案 1 :(得分:3)
我确实认为您应该使用$q
,因为您的应用程序的其他部分可能需要获得承诺。
一个很好的例子是 $routeProvider
解析选项。
我做了一点demo in plunker。
retrieveData function
应返回一个函数(返回一个promise)而不是一个promise。var retrieveEventDetails = function(events) {
// events is array
var deferred = $q.defer();
var promise = deferred.promise;
var retrieveData = function(data) {
return function(){
return $http({
url: '/api/eventdetails',
method: 'POST',
data: {
event_number: data.number
},
isArray: true
})
}
}
deferred.resolve();
return events.reduce(function(promise, single_event){
return promise.then(retrieveData(single_event));
}, promise);
}
答案 2 :(得分:1)
我不确定你在这里需要$q
。在这个例子中,每一条数据一旦从呼叫中返回就会在控制器中注册。
<强> Live demo (click). 强>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, myService) {
$scope.datas = myService.get();
});
app.factory('myService', function($http) {
var myService = {
get: function() {
var datas = {};
var i=0;
var length = 4;
makeCall(i, length, datas);
return datas;
}
}
function makeCall(i, length, datas) {
if (i < length) {
$http.get('test.text').then(function(resp) {
datas[i] = resp.data+i;
++i;
makeCall(i, length, datas);
});
}
}
return myService;
});
以下是使用$q.all()
的方法,您可以在将所有数据传递给控制器之前等待所有数据: Live demo (click).
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, myService) {
myService.get().then(function(datas) {
$scope.datas = datas;
})
});
app.factory('myService', function($q, $http) {
var myService = {
get: function() {
var deferred = $q.defer();
var defs = [];
var promises = [];
var i=0;
var length = 4;
for(var j=0; j<length; ++j) {
defs[j] = $q.defer();
promises[j] = defs[j].promise;
}
makeCall(i, length, defs);
$q.all(promises).then(function(datas) {
deferred.resolve(datas);
});
return deferred.promise;
}
}
function makeCall(i, length, defs) {
if (i < length) {
$http.get('test.text').then(function(resp) {
defs[i].resolve(resp.data+i);
++i;
makeCall(i, length, defs);
})
}
}
return myService;
});