Reputation: 8004
I am creating a "Web Planner" where the user has to complete a number of steps on different pages in order to create an order for our service. I know that I need to use a service in order to share certain data around the entire Planner, but I am still not sure how do go about it.
The problem is that the user will not necessarily go in-order every time. They can stop on any page, then come back later and resume, therefore I need a way to manage some API data so that if the user is on 1 of 2 pages that share the same data, the data will fetched from the server via API or simply assigned if the data was already taken.
Right now the only method I thought of is to place the API requests inside my Service as well, and then when I run something like OrderService.get()
the service will handle logic to check if the data was already grabbed from the server. If it was then it is just a simple assignment like $scope.model = OrderService.get()
, but then the problem is that if the data isn't loaded yet, then I need to use a promise somewhere to wait for the data, so a simple assignment operation won't suffice.
This service may look something like this:
app.factory('OrderService', function(){
var orders = []; // This is the actual data
var service = {};
service.get = function(id){
if(orders.length){
return orders; // This means there is already data available
}else{
// This is where I am not sure what to do...
// Maybe...
var promise = API.Orders.getAllOrders({id : id}, function(res){
// Not sure about how to implement this part
}).$promise;
return promise;
}
}
})
Does anyone have any other ideas?
Upvotes: 0
Views: 199
Reputation: 5542
Please bear in mind that I'm still a beginner (reading through a lot of documentation) so this might not be 100% correct.
Your service would be something like this:
app.factory('OrderService', function($q){
var orders = []; // This is the actual data
return {
getData: function(id){
var deferred = $q.defer();
if(orders.length){
deferred.resolve(orders); // This means there is already data available
}else{
$http.get('/api/get/data/' + id)
.success(function(data) {
deferred.resolve(data);
})
.error(function(){
deferred.reject();
});
}
return deferred.promise;
}
})
And then on your controllers you just need to use it like this:
app.controller('MainCtrl', function($scope, OrderService) {
var id = 1;
$scope.data = OrderService.getData(id);
});
Upvotes: 0
Reputation: 11752
Since your calls are asynchronous, the only way to do this is via promises
app.service('OrderService', function($q){ // import $q ; the angularjs promise
var orders = []; // This is the actual data
var service = {};
service.get = function(id){
var deferred = $q.defer(); // create a unit of work to be done; a promise
if(orders.length){ // if data is already available, resolve the promise
deferred.resolve(orders); // This means there is already data available, so mark as resolved and successful
}else{
// make your async call since you don't have data
API.Orders.getAllOrders({id : id}, function(response){
// here you can actually modify the response before it goes back to your controller
deferred.resolve(response);
}, function(reason){ // failure scenario
deferred.reject(reason);
})
}
return deferred.promise; // always return promise
}
})
Upvotes: 1
Reputation: 1954
Just return a promise all the time, whether the data is already there, or fetched by a call to a server. In your example..
if(orders.length){
return $q.when(orders); // This means there is already data available
}else{
// This is where I am not sure what to do...
// Maybe...
var promise = API.Orders.getAllOrders({id : id}, function(res){
// Not sure about how to implement this part
}).$promise;
return promise;
}
Upvotes: 1