There is really no concept of “service initialization” in angular. A service is just a singleton object returned by a factory function you registered in a module. For example:
myModule.factory("myService", function(){
return "THIS IS MY SERVICE";
});
There is no concept of initialization. Whenever you inject this service it simply calls the factory function ONCE and caches the return so all subsequent injections will use the same object:
function myController($scope, myService){
console.log(byService); // Will log "THIS IS MY SERVICE"
}
The resolve functionality of $routeProvider does not really know about services or have any concept of “service initialization”. It just works with promises and these promises can come from anywhere.
What you are referring to is likely the very common practice of having service methods return promises, and using resolve to postpone controller initialization until that promise is resolved. For example:
myModule.factory("userService", function(){
return {
getUsers: function(){
return $http.get('/users').then(function(response){
return response.data;
});
}
};
});
And then in your resolve:
resolve: {
users: function(userService){
return userService.getUsers() //returns a promise
}
}
If in order for the user service to return the users it depends on some other service method which is also async, there is nothing stopping it from waiting on the other services promise before resolving it’s own. For example:
myModule.factory("userService", function(someOtherService){
return {
getUsers: function(){
var otherServicePromise = someOtherService.doSomething();
return otherServicePromise.then( function(){
return $http.get('/users').then(function(response){
return response.data;
});
);
}
};
});
This is called “promise chaining” and is a very common and elegant solution to handling async things properly. The service will first call someOtherService.doSomething() which returns a promise. When that is resolved it will do the $http.get() to get the users. This will eventually resolve the promise with the response.data.
Because we are returning the last promise in the chain, our resolve will not conclude until every single promise in the chain has resolved, so this should handle any sort of dependency structure.
I see…. One thing you can do is have an “initialized” promise on each service:
app.service('serviceA', function($q, serviceB){
var initDefer = $q.defer();
this.initialized = initDefer.promise;
serviceB.initialized.then(function(){
doSomeServiceAsyncInit().then(function(){
initDefer.resolve();
});
});
}
app.service('serviceB', function($q){
var initDefer = $q.defer();
this.initialized = initDefer.promise;
doSomeAsyncInit().then(function(){
initDefer.resolve();
});
}
then in your route provider:
resolve: {
initServices: function(serviceA){ return serviceA.initialized }
}
Does this make sense?