In my Angular application, I have two controllers which both need access to the same data.
Toward that end, I've created a service which will be responsible for holding and providing access to that data:
angular.module("SomeModule").factory( "SomeService", function( $http ) {
var svc = {};
var data = {};
// on initialization, load data from the server
$http.get( "somefile.json" )
.success( function( data ) {
svc.data = data;
} );
svc.getItem = function( id ) {
// find the specified item within svc.data, and return its value
};
return svc;
} );
...and I've injected that service into each of the two controllers:
angular.module("SomeModule").controller( "SomeController", function( $routeParams, SomeService ) {
var ctrl = this;
ctrl.item = null; // set an initial value
// load the item that was requested in the URL
ctrl.item = SomeService.getItem( $routeParams.id );
} );
This almost works - but it has one big flaw. If SomeController
calls SomeService.getItem()
before SomeService
finishes loading somefile.json
, then SomeService
won't have any data to return.
In practice, if I load the app a few times, some loads will work (i.e., SomeService
will finish loading somefile.json
first, and the controller will present the data as desired), and other loads don't (i.e., SomeController
will try to retrieve data from SomeService
before the data has actually been loaded, and everything will crash and burn).
Obviously, I need to find some way to defer the execution of getItem()
until SomeService
is actually ready to process those calls. But I'm not sure of the best way to do that.
I can think of a some rather hairy solutions, such as building my own call queue in SomeService
, and wiring up a bunch of complicated callbacks. But there's gotta be a more elegant solution.
I suspect that Angular's $q service could be useful here. However, I'm new to promises, and I'm not sure exactly how I should use $q
here (or even whether I'm barking up the right tree).
Can you nudge me in the right direction? I'd be super grateful.
Here is how i did it in my own project.
Your Service
angular.module("SomeModule").factory( "SomeService", function( $http ) {
var svc = {};
svc.data = {};
// on initialization, load data from the server
svc.getData = function(){
return $http.get( "somefile.json" );
};
return svc;
} );
Your Controllers
angular.module("SomeModule").controller( "SomeController", function( $routeParams, SomeService ) {
ctrl.items = null; // set an initial value
// load the item that was requested in the URL
SomeService.getData().success(function(data){
ctrl.items = data;
}).error(function(response){
console.err("damn");
});
} );
Important point : Promises
In my humble opinion, the responsibility for processing asynchronous call is due to the controller. I always return a $http promiss whenever i can.
svc.getData = function(){
return $http.get( "somefile.json" );
};
You can add some logic in your service but you always have to return the promise. (To know : .success() on a promise return the promise)
The controller will have the logic to know how to behave depending to the response of your asynchronous call. He MUST know how to behave in case of success and in case of error.
If you have more question feel free to ask. I hope it helped you.