[英]How can I force this AngularJS service to wait until it has a value to return?
我有一个被多个控制器调用的服务。 它将数据加载到对象categories
:
.service('DataService', ['$http', '$q', function($http, $q) {
var categories = {};
// Return public API.
return({
setCategory: setCategory,
getCategory: getCategory,
getJSON: getJSON,
categories: categories
});
function setCategory(name, category) {
console.log("setting category");
console.log(name, category)
categories[name] = category;
}
function getCategory(name) {
console.log("getCategories:");
console.log(categories[name]);
return categories[name];
}
function getJSON() {
//JSON stuff, where categories gets its initial values.
}
我在很多地方都叫getCategory(name),在某些情况下,它是在categories
填充之前被调用的,例如:
$scope.category = DataService.getCategory(name);
//$scope.category is undefined
我如何构建此服务,以便getCategories在返回值之前一直等到类别已定义? 或者,如何编写Controller以便在类别具有值之前不定义getCategories? 我尝试在控制器中使用$ scope。$ watch函数来监视DataService.categories,但没有成功-它从不记录更新后的值。
使用您已经在服务中注入的承诺。 这只是执行此操作的许多可能方式之一:
var pendingQueue = [];
var loaded = false;
var self = this;
function getCategory(name) {
var deferred = $q.defer();
if (loaded) {
// Resolve immediately
console.log('Already loaded categories, resolving immediately...');
deferred.resolve(self.categories[name]);
return deferred.promise;
}
// Queue the request
pendingQueue.push({
promise: deferred.promise,
name: name
});
if (pendingQueue.length === 1) {
console.log('First request for a category, requesting...
// We are the FIRST request. Call whatever it takes to load the data.
// In a 'real' language this wouldn't be thread-safe, but we only have one, so...
$http.get('/my-data').then(function(data) {
self.categories = data;
console.log('Loaded categories', self.categories);
loaded = true;
pendingQueue.map(function(entry) {
entry.promise.resolve(entry.name);
});
pendingQueue.length = 0;
});
}
return deferred.promise;
}
然后在您的控制器中:
DataService.getCategory(name).then(function(category) {
// Do something with category here
});
这将:
对于第一个请求,请发出异步请求,然后在获取数据后解析承诺。
对于第二个-第N个请求,在获取数据之前,对那些没有重复请求的请求进行排队。
对于获取数据后的请求,请立即使用请求的数据进行解析。
没有错误处理可以完成-您应该使用deferred.reject()将其发送回调用方,并使用.catch()/ .finally()在控制器中进行处理。
解决方案有很多-这只是一种选择。
内部数据服务
yourApp.service('DataService', function($resource, $q) {
var resource = $resource('/api/category/:id', {}, {
query: {
method: 'GET',
isArray: false,
cache: false
},
save: {
method: 'POST',
isArray: false,
cache: false
}
});
return {
getCategory: function(id) {
var deferred = $q.defer();
resource.query({id: id},
function(response) {
deferred.resolve(response);
},
function(response) {
deferred.reject(response);
}
);
return deferred.promise;
},
setCategory: function(categoryObj) {
var deferred = $q.defer();
resource.save(categoryObj,
function(response) {
deferred.resolve(response);
},
function(response) {
deferred.reject(response);
}
);
return deferred.promise;
},
getJSON: function() {
// stuff to do
}
};
});
内部DataController:
yourApp.controller('DataCtrl', function($scope, DataService) {
$scope.handleSuccessResponse = function(response) {
$scope.data = response;
};
$scope.handleErrorResponse = function(response) {
$scope.error = response;
};
DataService.getCategory(123).then($scope.handleSuccessResponse, $scope.handleErrorResponse);
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.