Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: don't instantiate providers with ngOnDestroy eagerly. #15070

Merged
merged 1 commit into from
Mar 14, 2017

Conversation

tbosch
Copy link
Contributor

@tbosch tbosch commented Mar 10, 2017

Perviously, any provider that had an ngOnDestroy lifecycle hook would be created eagerly. Now, only classes that are annotated with @component, @directive, @pipe, @NgModule are eager. Providers only become eager if they are either directly or transitively injected into one of the above.

Fixes #14552

@brandonroberts
Copy link
Contributor

Wouldn't this be considered a breaking change?

@tbosch tbosch force-pushed the noeager branch 2 times, most recently from 14d0f86 to 13982cb Compare March 10, 2017 21:47
@tbosch
Copy link
Contributor Author

tbosch commented Mar 10, 2017

Marked in the commit message as breaking change with small impact.

@tbosch tbosch force-pushed the noeager branch 2 times, most recently from ed796b7 to 9403853 Compare March 13, 2017 15:43
BREAKING CHANGE:

Perviously, any provider that had an ngOnDestroy lifecycle hook would be created eagerly.

Now, only classes that are annotated with @component, @directive, @pipe, @NgModule are eager. Providers only become eager if they are either directly or transitively injected into one of the above.

This also makes all `useValue` providers eager, which
should have no observable impact other than code size.

EXPECTED IMPACT:
Making providers eager was an incorrect behavior and never documented.
Also, providers that are used by a directive / pipe / ngModule stay eager.
So the impact should be rather small.

Fixes angular#14552
@chuckjaz chuckjaz merged commit 2c5a671 into angular:master Mar 14, 2017
@tbosch tbosch deleted the noeager branch March 17, 2017 15:28
SamVerschueren pushed a commit to SamVerschueren/angular that referenced this pull request Mar 18, 2017
…5070)

BREAKING CHANGE:

Perviously, any provider that had an ngOnDestroy lifecycle hook would be created eagerly.

Now, only classes that are annotated with @component, @directive, @pipe, @NgModule are eager. Providers only become eager if they are either directly or transitively injected into one of the above.

This also makes all `useValue` providers eager, which
should have no observable impact other than code size.

EXPECTED IMPACT:
Making providers eager was an incorrect behavior and never documented.
Also, providers that are used by a directive / pipe / ngModule stay eager.
So the impact should be rather small.

Fixes angular#14552
@casperchia
Copy link

casperchia commented Mar 25, 2017

This was a breaking change for us. Is there a way to make an @Injectable() instantiate eagerly? We have @Injectable() services that listens for events then performs some logic whenever such events are fired, hence they never had to be injected anywhere. Now it looks like to instantiate these services we would have to inject them through the constructor even though we never call these services directly. Which can be annoying since we now have constructors with 20+ services that are never actually referenced.

This is an example of such a service:

@Injectable()
export class SubmitEventListener {
   constructor(private eventService: EventService) {
      this.eventService.events.subscribe(event => doSomething());
   }

   doSomething() {
      console.log("hello world");
   }
}

Could we make @Injectable() take in an option to instantiate eagerly?
@Injectable({eager: true})

or perhaps something like this:

providers: [
   {provide: SubmitEventListener, useClass: SubmitEventListener, eager: true}
]

I'd be happy to submit a PR if I can get some directions on where to look.

@tbosch
Copy link
Contributor Author

tbosch commented Mar 25, 2017 via email

@casperchia
Copy link

casperchia commented Mar 25, 2017

Thanks for the quick response!

Using multi providers as suggested worked just fine. Not too sure about using APP_INITIALIZER though, the official docs doesn't say much about it at the moment.

For reference, here is what I did (following the example above):

const EVENT_LISTENERS: InjectionToken<any> = new InjectionToken('eventListeners');

@NgModule({
   providers: [
      {provide: EVENT_LISTENERS, useClass: SubmitEventListener, multi: true},
      {provide: EVENT_LISTENERS, useClass: OtherEventListener, multi: true},
      {provide: EVENT_LISTENERS, useClass: AnotherEventListener, multi: true},
   ]
})
export class MyModule {
   constructor(@Inject(EVENT_LISTENERS) eventListeners: any[]) {}
}

Thanks @tbosch !

@wKoza
Copy link
Contributor

wKoza commented Mar 25, 2017

@casperchia , there is an example here.

@DzmitryShylovich
Copy link
Contributor

@casperchia there's an issue for discussion #13960

smurfy pushed a commit to smurfy/angular that referenced this pull request Apr 7, 2017
…5070)

BREAKING CHANGE:

Perviously, any provider that had an ngOnDestroy lifecycle hook would be created eagerly.

Now, only classes that are annotated with @component, @directive, @pipe, @NgModule are eager. Providers only become eager if they are either directly or transitively injected into one of the above.

This also makes all `useValue` providers eager, which
should have no observable impact other than code size.

EXPECTED IMPACT:
Making providers eager was an incorrect behavior and never documented.
Also, providers that are used by a directive / pipe / ngModule stay eager.
So the impact should be rather small.

Fixes angular#14552
asnowwolf pushed a commit to asnowwolf/angular that referenced this pull request Aug 11, 2017
…5070)

BREAKING CHANGE:

Perviously, any provider that had an ngOnDestroy lifecycle hook would be created eagerly.

Now, only classes that are annotated with @component, @directive, @pipe, @NgModule are eager. Providers only become eager if they are either directly or transitively injected into one of the above.

This also makes all `useValue` providers eager, which
should have no observable impact other than code size.

EXPECTED IMPACT:
Making providers eager was an incorrect behavior and never documented.
Also, providers that are used by a directive / pipe / ngModule stay eager.
So the impact should be rather small.

Fixes angular#14552
juleskremer pushed a commit to juleskremer/angular that referenced this pull request Aug 28, 2017
…5070)

BREAKING CHANGE:

Perviously, any provider that had an ngOnDestroy lifecycle hook would be created eagerly.

Now, only classes that are annotated with @component, @directive, @pipe, @NgModule are eager. Providers only become eager if they are either directly or transitively injected into one of the above.

This also makes all `useValue` providers eager, which
should have no observable impact other than code size.

EXPECTED IMPACT:
Making providers eager was an incorrect behavior and never documented.
Also, providers that are used by a directive / pipe / ngModule stay eager.
So the impact should be rather small.

Fixes angular#14552
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 11, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

bug: service instantiated eagerly when it has a lifecycle hook
9 participants