Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Conversation

@ctrahey
Copy link

@ctrahey ctrahey commented Jul 22, 2013

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 ;-)

@petebacondarwin
Copy link
Contributor

PR Checklist (Major Feature)

  • Contributor signed CLA now or in the past (if you just signed, leave a comment here with your real name)
  • Feature is focused on a core value of the framework
  • PR is approved by 2+ senior team members and no committer is blocking the change
  • API is compatible with existing Angular apis and relevant standards (if applicable)
  • Breaking change check
    • No breaking change
    • Intentional breaking change
      • Approved by 2+ senior team members
      • The breaking change is documented (including migration steps)
  • PR contains unit tests
  • PR contains e2e tests (if suitable)
  • PR contains documentation update
  • PR passes all tests on Travis (sanity)
  • PR passes all tests on ci.angularjs.org (cross-browser compatibility)
  • PR is rebased against recent master
  • PR is squashed into one commit per logical change
  • PR's commit messages are descriptive and allows us to autogenerate release notes (required commit message format)
  • All changes requested in review have been implemented

@petebacondarwin
Copy link
Contributor

@ctrahey - have you signed the CLA? Can you take a look at our commit message guidelines too?
Thanks

@ctrahey
Copy link
Author

ctrahey commented Jul 23, 2013

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.
@ctrahey
Copy link
Author

ctrahey commented Jul 23, 2013

@petebacondarwin I have updated the commit message :-)

@morgs32
Copy link

morgs32 commented Jul 25, 2013

I just wanted to support your work, @ctrahey ! Keep it up - I'll be in line to use it.

@ewinslow
Copy link
Contributor

👍 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.

@christianacca
Copy link

+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

@ctrahey
Copy link
Author

ctrahey commented Aug 16, 2013

@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?

@leifhanack
Copy link

Great. Is there a planned date when it will be "officially" available?
Thanks a lot.

@eahutchins
Copy link

@ctrahey this is possibly a different feature, but it would be very useful for angular.injector to accept promises in addition to module functions/aliases as requirements. Since you've already got an asynchronous behavior specified for the injector these features might belong together, what do you think? This would allow lazy-loading modules more easily for example.

@jonnysamps
Copy link

+1 Would love this feature.

@just-boris
Copy link
Contributor

+1 this fix is small, but it brings many benefits

@michaelhunziker
Copy link

+1!

@blakeholl
Copy link

This would be extremely helpful. I am having to rely on some very "clever" workarounds right now

@czjvic
Copy link

czjvic commented Apr 2, 2014

+1

1 similar comment
@vvatikiotis
Copy link

+1

@caitp
Copy link
Contributor

caitp commented Oct 27, 2014

so, do we want to do this? I don't feel like it makes a lot of sense, because it makes invoke() / get() asynchronous

@just-boris
Copy link
Contributor

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 profileData three times (even 4 with annotation for minify) looks a bit strange

@caitp
Copy link
Contributor

caitp commented Oct 27, 2014

yeah I get that it's inconvenient to support synchronous stuff, but it's like, right now inject() is always synchronous --- this is really nice for tests. It gets really bad when you have functions that are sometimes synchronous and sometimes not (see the compiler for instance)... So I don't think we want to build that in.

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.

@gregjhogan
Copy link
Contributor

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:

  • write a shim for any asynchronous module loading library
  • create services that prefetch data only once (upon instantiation)
  • create decorators that perform asynchronous actions

ctrahey pushed a commit to ctrahey/servorkers that referenced this pull request Sep 16, 2015
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.
@petebacondarwin
Copy link
Contributor

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 resolve in ngRoute. This will block a navigation transition until a set of promises have resolved.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.