Reputation: 105029
I have an AngularJS app that uses routing and views. When a particular view is loaded and controller instantiates I have to prepare some $scope
model data. This data can be provided by a dependent service or when service doesn't have it, I make an async call to get it from the server.
When I finally do have this data I have to change it a bit and then put it on my $scope
.
This I think perfectly falls into deferred/promise API. Getting data from the service is done using $resource
service instance and is a promise already. The only problem I'm having is converting my synchronous code to a deferred/promise pattern.
How can I change my synchronous code processing to become async so my function that provides data always returns a promise which would be immediately resolved when using sync code and after a while when asynchronously calling my server?
var getData = function() {
var defer = $q.defer();
defer.promise
.then(function () {
// return cached item
return dataCacheService.get("dataKey");
})
.then(function(data) {
// cache returned data?
if (!data)
{
// no? get it from server returning a promise
return dataResource.get({
set: "models",
id: $routeParams.id
});
}
})
.then(function (data) {
// server returned data?
if (!!data) // <= PROBLEM!!! This is not null, but is a Resource with unresolved promise?
{
// yes? fine. manipulate it
delete data.details;
delete data.type.description;
$scope.lists.set(data.type);
return data;
}
// no data. sorry...
$scope.resetType();
})
// something went wrong
.catch($scope.resetType);
// initiate deferred execution
defer.resolve();
return defer.promise;
}
...
$scope.model = {
item: getData()
};
Upvotes: 3
Views: 729
Reputation: 17492
You can make your service such that it always returns a promise, if the data is available it will return the promise immediately otherwise after a REST call. For example your service might look like:
var dataThatMayOrMayNotBeAvailable=null;
var getDataThatMayOrMayNotBeAvailable=function(){
var deferred = $q.defer();
if(dataThatMayOrMayNotBeAvailable){
deferred.resolve(dataThatMayOrMayNotBeAvailable);
}else{
$http({...}).success(function(data){
dataThatMayOrMayNotBeAvailable=data;
deferred.resolve(data);
});
}
return deferred.promise;
}
Usage:
getDataThatMayOrMayNotBeAvailable().then(function(data){
console.log(data);
})
Upvotes: 3