我当前的实现有多个控制器使用服务访问相同的JSON数据集。我希望能够在单个查询中解决在正在进行的HTTP请求期间中出现的多个请求。
app.factory('dataService', function($http, $q) {
var promises = [];
var busy = false;
return {
getData: function() {
if (busy) {
var p = $q.defer();
promises.push(p);
return p.promise;
}
busy = true;
var promise = $http.get('data.json').then(function(response) {
while (promises.length > 0) {
promises.pop().resolve(response.data);
}
busy = false;
return response.data;
}, function(error) {
while (promises.length > 0) {
promises.pop().reject(error);
}
busy = false;
});
return promise;
}
}
});
app.controller('Ctrl1', function($scope, dataService) {
$scope.logger = "";
function getIt(a) {
dataService.getData().then(function(d) {
$scope.logger += 'Request '+a+': '+(new Date).getTime()+'\n';
});
}
// These will be resolved in a 'batch'
getIt(1);
setTimeout(function(){getIt(2)},100);
setTimeout(function(){getIt(3)},0);
// This will be resolved in the 'next batch'
setTimeout(function(){getIt(4)},2000);
setTimeout(function(){getIt(5)},2100);
});
KenBurnsView示例。
假设请求的顺序并不重要,有没有更好的方法来执行此操作,或者是否存在可能潜伏在此技术中的任何缺陷?
答案 0 :(得分:3)
你实际上并不需要多次承诺。您可以在同一回合中向每个呼叫者发出相同的承诺:
app.factory('dataService', function($http, $q) {
var busyPromise = null;
return {
getData: function() {
if (!busyPromise) {
busyPromise = $http.get('data.json').finally(function() {
busyPromise = null;
});
}
return busyPromise;
}
}
});
答案 1 :(得分:1)
代码看起来没问题,但我认为defer
已被弃用,请注意.then(success, fail)
反模式,例如,您为所有等待的承诺抛出错误,它将被隐藏打电话的实际人。所以我会改为:
app.factory('dataService', function($http, $q) {
var promises = [];
var busy = false;
return {
getData: function() {
if (busy) return new Promise((res, rej) => promises.push({res, rej}));
busy = true;
return $http.get('data.json').then(response => {
promises.forEach( promise => promise.res(response.data));
promises = [];
busy = false;
}).catch( e => {
promises.forEach( promise => promise.rej(e));
promises = [];
busy = false;
throw e;
});
}
}
});