I need to get some information (a schema) from the server before I set up a bunch of services that depend on that information.
My server provides a schema that defines various properties of a model. In my angular code, I have a service that gets this schema:
services.factory('schema', function($q, $http) {
var deferred = $q.defer();
$http.get('schema/').then(function(response) {
schema = // some function of response.data
deferred.resolve(schema);
}, function() {
deferred.reject('There was a problem fetching the schema');
});
return deferred.promise;
});
I would like to inject the schema object, and not the promise, into other services that depend on the schema. $routeProvider lets us do this for controllers:
app.config(function($routeProvider) {
$routeProvider.
when('/', {
controller: 'SomeCtrl',
resolve: {
schema: 'schema'
},
...
});
});
and this allows me to define SomeCtrl like this:
controllers.controller('SomeCtrl', function($scope, schema) {
// schema is an object
...
});
But for services, I have to do:
services.factory('SomeService', function(schema) {
// schema is a promise
schema.then(function(schema) {
...
});
});
Is there any way I can do this?
I need to get some information (a schema) from the server before I set up a bunch of services that depend on that information.
My server provides a schema that defines various properties of a model. In my angular code, I have a service that gets this schema:
services.factory('schema', function($q, $http) {
var deferred = $q.defer();
$http.get('schema/').then(function(response) {
schema = // some function of response.data
deferred.resolve(schema);
}, function() {
deferred.reject('There was a problem fetching the schema');
});
return deferred.promise;
});
I would like to inject the schema object, and not the promise, into other services that depend on the schema. $routeProvider lets us do this for controllers:
app.config(function($routeProvider) {
$routeProvider.
when('/', {
controller: 'SomeCtrl',
resolve: {
schema: 'schema'
},
...
});
});
and this allows me to define SomeCtrl like this:
controllers.controller('SomeCtrl', function($scope, schema) {
// schema is an object
...
});
But for services, I have to do:
services.factory('SomeService', function(schema) {
// schema is a promise
schema.then(function(schema) {
...
});
});
Is there any way I can do this?
Share Improve this question edited Jul 25, 2014 at 3:43 Bergi 666k161 gold badges1k silver badges1.5k bronze badges asked Aug 2, 2013 at 13:51 user2463201user2463201 7352 gold badges7 silver badges11 bronze badges 2- Nope, that's just how it works, at least for now. – aet Commented Sep 17, 2013 at 18:54
-
The angular router waits for the values within
resolve
to resolve/reject before instantiating the controller. Then it uses local values to inject into the controller (the angular injector prefers locals). TL;DR: you're working with two differentschema
s. – James Kyle Commented Feb 11, 2014 at 20:15
2 Answers
Reset to default 5What you want is deferred bootstrap. There is already a plugin written for this purpose - https://github./philippd/angular-deferred-bootstrap.
I create an example at plunkr - http://plnkr.co/edit/VfISHNULXRLe52NeAsn1?p=preview
*You must replace existing ng-app with deferred bootstrap
Code Snippet -
angular.element(document).ready(function() {
deferredBootstrapper.bootstrap({
element: document.body,
module: 'plunker',
resolve: {
schema: ['$http',
function($http) {
return $http.get('schema.json');
}
]
}
});
});
Then, you can use schema anyway in controller, services or factory just like route resolve.
Sample Code for Factory
app.factory('SomeService', function(schema){
return {
getTitle: function() {
return schema.title;
}
}
});
You get a promise because your service function immediately evaluates its body when you call it (as functions do). Normally, a service should return an object so that the consumer (another service, controller, whatever) may then call the functions on that object when it needs to.
services.factory('schema', function($q, $http) {
return {
get: function() {
var deferred = $q.defer();
$http.get('schema/').then(function(response) {
schema = // some function of response.data
deferred.resolve(schema);
}, function() {
deferred.reject('There was a problem fetching the schema');
});
return deferred.promise;
}
}
});