Reputation: 5144
I've been using resolves extensively in my angular project and it has come to a point where for the sake of readability I want to move all of my resolve functions to independent modules (some states would then even be able to share the same resolve functions without me having to rewrite them).
So, a simplified example of what I had:
angular.module("stream", [
"resources.groups",
"ui.router"
]).config(function ($stateProvider) {
$stateProvider.state("stream", {
url: ... ,
views: ... ,
resolve: {
groups: function (groups) {
console.log("Resolving groups");
return groups.get();
}
}
}
});
angular.module("conversations", [
"resources.groups",
"ui.router"
]).config(function ($stateProvider) {
$stateProvider.state("conversations", {
url: ... ,
views: ... ,
resolve: {
groups: function (groups) {
console.log("Resolving groups");
return groups.get();
}
}
}
});
In this case, "Resolving groups" would be logged every single time the state changed to either stream or conversations from whichever other states (except of course child states of stream and conversations). Eg, visit stream (groups resolved) -> visit state3 -> visit conversations (groups resolved) -> visit stream (groups resolved)
However, when I refactored it to the following, the resolve is now only ever called once when I visit whichever state it is used on. Eg, visit state3 -> visit stream (groups resolved) -> visit conversations (NOT resolved here or ever again) -> visit state3 -> visit stream -> visit conversations ...
. The following caused this behavior:
angular.module("stream", [
"resolves.groups",
"ui.router"
]).config(function ($stateProvider) {
$stateProvider.state("stream", {
url: ... ,
views: ... ,
resolve: {
groups: "resolveGroups"
}
}
});
angular.module("conversations", [
"resolves.groups",
"ui.router"
]).config(function ($stateProvider) {
$stateProvider.state("conversations", {
url: ... ,
views: ... ,
resolve: { groups: "resolveGroups" }
}
}
});
angular.module("resolves.groups", [
"resources.groups"
]).factory("resolveGroups", function (groups) {
return groups.get();
});
How do I achieve a situation where the resolve function is shared and reused from an external service, but it still executes every time there is a transition to a state which uses it?
Upvotes: 1
Views: 305
Reputation: 6061
The problem with the service approach is that AngularJS services are singletons, so they will be (lazily) instantiated only once.
However, since the injectables which are mapped to names in resolve
objects are nothing more than simple independent data structures (arrays of strings and a function at the end), you can expose them at config-time in a constant :
angular.module('myApp.resolvers')
.constant('myAppResolvers', {
groups: ['groups', function (groups) {
return groups.get();
}],
myOtherThing: ['$http', 'myService', '$q', function ($http, myService, $q) {
// code for resolving some other thing
}]
});
And then in your config :
myApp.config('$stateProvider','myAppResovers', function ($stateProvider, myAppResolvers) {
$stateProvider.state("stream", {
url: ... ,
views: ... ,
resolve: {
groups: myAppResolvers.groups
}
}
So code reuse is achieved.
Upvotes: 1