-
Notifications
You must be signed in to change notification settings - Fork 27.3k
Allow service factory functions to return promises #3295
Conversation
PR Checklist (Major Feature)
|
|
@ctrahey - have you signed the CLA? Can you take a look at our commit message guidelines too? |
|
I have signed the CLA, yes. Looking into Commit msg guidlines now. |
Change $injector's invoke method to delay the invocation in the event that an injected service is a promise. The change allows user-land services to be constructed asyncronously if they simply return a promise from their factory function. For any invocation that does not have promises as dependencies, the invocation happens immediately, as though this change was not in place. It may be interesting to note that in cases where the invocation does have promise (async-fulfilled) dependencies, the call to invoke will itself return a promise. There is ongoing discussion as to the merrits of this relatively non-deterministic behavior, though it is not considered 'BREAKING' because currently there is no support for asynchronously-generated services.
|
@petebacondarwin I have updated the commit message :-) |
|
I just wanted to support your work, @ctrahey ! Keep it up - I'll be in line to use it. |
|
👍 would love this kind of async support in the DI system. It would allow lazy-loading code without having to buy into any one loader or module system. |
|
+1 The fact that angular run blocks do not wait on promises before returning means that ensuring that a service is fully initialized before it is first used is a real pain. route.resolve goes some way to help but does not accommodate all scenarios plus it creates unnecessary verbose / duplicate code. Dependency injector waiting on promises before it resolves the dependency chain would be incredibly useful. By adding this feature it would stop people having to come up with dubious "solutions" like this one: http://stackoverflow.com/questions/16286605/initialize-angularjs-service-with-asynchronous-data#answer-16340429 |
|
@petebacondarwin I've been thinking lately about taking this to the next level with respect to the non-deterministic return-type of invoke(). If it's the right direction, I could look into altering this PR to include always returning a promise from invoke(), and then working out all the places where that induces change elsewhere in Angular (e.g. make all consumers of invoke() promise-aware. Does this seem worth the effort? Is it the kind of change that this idea needs? If not, how else might I improve this? |
|
Great. Is there a planned date when it will be "officially" available? |
|
@ctrahey this is possibly a different feature, but it would be very useful for |
|
+1 Would love this feature. |
|
+1 this fix is small, but it brings many benefits |
|
+1! |
|
This would be extremely helpful. I am having to rely on some very "clever" workarounds right now |
|
+1 |
1 similar comment
|
+1 |
02dc2aa to
fd2d6c0
Compare
cad9560 to
f294244
Compare
8292c21 to
7b9fddf
Compare
4dd5a20 to
998c61c
Compare
|
so, do we want to do this? I don't feel like it makes a lot of sense, because it makes |
|
Now I have a little workaround to load services asynchronously: angular.module('myApp', []).factory('profileData', function($http) {
return $http.get('/app/profile')
}).config(function($routeProvider) {
$routeProvider.when('/profile', {
controller: 'ProfileController',
resolve: {
profileData: function(profileData) {return profileData;}
}
});
}).controller('ProfileController', function($scope, profileData) {
//here we have a user data loaded through asynchronous request
$scope.user = profileData;
});It covers most of my use-cases, but I'd like to have more convenient way to do it. Repeating |
|
yeah I get that it's inconvenient to support synchronous stuff, but it's like, right now We could probably change the injector to support async injection too, and offer a way to annotate that a service needs to be injected asynchronously --- but I think the testing story is going to suck pretty much no matter what. Anyways, I'm happy to hear ideas for stuff like this. |
|
It looks like perhaps this has lost all traction, but I would still really like to see dependency injection become completely asynchronous. It seems like it would really open a lot of doors new doors, such as:
|
Will likely abandon this branch in favor of Babel proxies. Here, we use defered Service factories (angular/angular.js#3295) Working toward loading the service in the other thread prior to injecting them.
|
We have looked into this, both in Angular 1 and Angular 2. Dependency Injection needs to be all synchronous or all asynchronous. As soon as one part is async then you have to make it all the same. Further, making all DI async would be detrimental to the performance and maintainability of the core; and would also impact on the ease of use of the DI system in a number of cases for the application developer. Angular 2 has not implemented async DI and we are not to do it Angular 1 either. Sorry. There are some patterns for achieving the kind of thing you want. The most common being the use of |
Here is a cleaned up PR for allowing User-Defined Services to be promise-fulfilled.
The original PR (Which I subsequently ruined with sloppy Giting... oops) is here: #3195
This PR includes docs changes as well as unit tests in addition to moving some of the logic into $q.all() as suggested.
Please see discussion on the old PR, and as always don't hesitate to take me to school ;-)