我正在尝试构建一个允许我通过某些API调用加载日期的服务或工厂。 大多数这些数据都需要重复使用,所以基本上我只想进行一次API调用,下次当我需要这些数据时,它应该只返回它。
现在无论何时我进行API调用,在它完成之前我都进行相同的调用,我希望第二次调用等到第一次调用完成。
基本上当我这样做时:
dataService.getMenu() // Make API call
dataService.getMenu() // Wait for the first API call to be completed and return that data
// Somewhere else
dataService.getMenu() // Return data as API call was already made
我的工厂看起来像这样:
(function() {
var app = angular.module('dataService', []);
app.factory('dataService', ['$http', '$q', function($http, $q) {
var links = [],
jobs = [];
return {
getMenu: function() {
var deferred = $q.defer();
console.log(links);
if(links.length > 0) {
deferred.resolve(links);
} else {
$http.get('../server/api.php?ajax=true&action=getCats').success(function(data) {
links = data;
deferred.resolve(data);
})
}
return deferred.promise;
}
}
}])
})();
答案 0 :(得分:2)
只需将getMenu函数之外的defer声明移到工厂
即可 app.factory('dataService', ['$http', '$q', function($http, $q) {
var links = [],
jobs = [],
deferredMenu = $q.defer();
现在在getMenu调用中使用deferredMenu promise。
getMenu: function() {
if(links.length > 0) {
deferredMenu.resolve(links);
} else {
$http.get('../server/api.php?ajax=true&action=getCats').success(function(data) {
links = data;
deferredMenu.resolve(data);
})
}
return deferredMenu.promise;
}
答案 1 :(得分:0)
您可以使用cache
服务中的$http
配置为您执行此操作。如 $http
caching 文档中所述:
要启用缓存,请将请求配置缓存属性设置为 true(使用默认缓存)或自定义缓存对象(使用 $ cacheFactory)。启用缓存后,$ http将存储响应 来自指定缓存中的服务器。 下次同样的请求 生成后,响应将从缓存中提供,而不会发送 请求服务器
请注意,即使响应是从缓存提供的,也是如此 数据的异步方式与实际请求的方式相同。
如果对同一个URL有多个GET请求 使用相同的缓存进行缓存,但仅缓存尚未填充 将向服务器发出一个请求,其余请求将 使用第一个请求的响应来实现。
上述声明符合您问题中的要求。此外,我省略了$q
服务,因为$http
方法已经提供了您需要的承诺,您只需要使用then()
$q
服务在响应中包含数据对象方法
(function() {
var app = angular.module('dataService', []);
app.factory('dataService', ['$http', function($http) {
return {
getMenu: function() {
return $http.get('../server/api.php?ajax=true&action=getCats', {cache: true})
.then(function(response) {
return response.data;
});
}
};
}])
})();
答案 2 :(得分:0)
我知道我回答这个问题有点迟了,但我遇到了同样的问题,经过大量研究后提出了一个解决方案。
达到上述要求的方法是使用呼叫排队。
以下是相同的步骤:
defer.promise
。 IsDataPresent = true
(最初为假)。IsDataPresent=== true
,如果为true,则使用局部变量数据解析下一个调用的promise。请参阅以下代码:
app.factory('dataService', ['$http', '$q', function($http, $q) {
var links = '',
jobs = [],
isDataAlreadyPresent = false;
var getMenuCall = function() {
var call = jobs[0]; // Retrieve first promise from the queue
if (isDataAlreadyPresent) { // This will be false for first call and true for all other
call.defer.resolve(links);
} else {
$http.get('../server/api.php?ajax=true&action=getCats').success(function(data) { //Get API data
isDataAlreadyPresent = true; //Set parameter to true
links = data; // Set local variable to received data
call.defer.resolve.resolve(data); // Resolve the first promise
jobs.shift(); // Remove first item from the queue
if (jobs.length > 0) {
getMenuCall(); // Execute the function for next call's promise in the queue. This time isDataAlreadyPresent== true will be true so it's promise will be resolved by the links data thus avoiding extra call.
}
});
}
return deferredMenu.promise;
};
return {
getMenu: function() {
var defer = $q.defer(); // Create promise for the call
jobs.push({
defer: defer // Push each call's promise to the queue
});
if (jobs.length === 1) { // For the first call make call above function which will make API call
getMenuCall();
}
return defer.promise; // Defer promise for the time being
}
}
}]);