Skip to content

Eager providers and Injector.get() can cause errors #15501

Closed

Description

@ph55

I'm submitting a ... (check one with "x")

[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

After updating from 4.0.0-rc.2 to 4.0.0 Router not injected as expected

Expected behavior

Should be injected as expected

Minimal reproduction of the problem with instructions

Plunker: http://plnkr.co/edit/ogCHjeYuCDM8vNLdwAFx?p=preview

Update from 4.0.0-rc.2 to 4.0.0

ConfigService provided in AppModule as APP_INITIALIZER

  providers: [
    ConfigService,
    {
      provide: APP_INITIALIZER,
      useFactory: configServiceFactory,
      deps: [ConfigService],
      multi: true
    }
  ],

ApiService injected manually from ConfigService

@Injectable()
export class ConfigService {

  private api: ApiService;

  public constructor(
    private injector: Injector
  ) {

    // Avoid cyclid dependencies, inject manually:
    this.api = injector.get(ApiService);
  }

router is undefined when injected in ApiService

import { Http, Headers, RequestOptionsArgs, Response } from '@angular/http';
import { Router } from '@angular/router';

@Injectable()
export class ApiService {

  constructor(
    private router: Router,
    private http: Http
  ) {

    console.log(router, 'router'); // undefined
    debugger;

What is the motivation / use case for changing the behavior?

Please tell us about your environment:

@angular/cli: 1.0.0
node: 7.4.0
os: win32 x64
@angular/animations: 4.0.0
@angular/common: 4.0.0
@angular/compiler: 4.0.0
@angular/compiler-cli: 4.0.0
@angular/core: 4.0.0
@angular/forms: 4.0.0
@angular/http: 4.0.0
@angular/platform-browser: 4.0.0
@angular/platform-browser-dynamic: 4.0.0
@angular/platform-server: 4.0.0
@angular/router: 4.0.0
@angular/material: 2.0.0-beta.2
@angular/flex-layout: 2.0.0-rc.1
@angular/cli: 1.0.0
@ngtools/webpack: 1.3.0

  • Angular version: 4.0.0
  • Browser: all

  • Language: TypeScript 2.2.1

  • Node (for AoT issues): node --version = 7.4.0

The log given by the failure.

core.es5.js:1085 ERROR TypeError: Cannot read property 'url' of undefined
    at CatchSubscriber.selector (api.service.ts:127)
    at CatchSubscriber.error (catch.js:104)
    at MapSubscriber.Subscriber._error (Subscriber.js:128)
    at MapSubscriber.Subscriber.error (Subscriber.js:102)
    at XMLHttpRequest.onLoad (http.es5.js:1210)
    at ZoneDelegate.invokeTask (zone.js:363)
    at Object.onInvokeTask (core.es5.js:4136)
    at ZoneDelegate.invokeTask (zone.js:362)
    at Zone.runTask (zone.js:166)
    at XMLHttpRequest.ZoneTask.invoke (zone.js:416)
defaultErrorLogger @ core.es5.js:1085
ErrorHandler.handleError @ core.es5.js:1145
next @ core.es5.js:4774
schedulerFn @ core.es5.js:3848
SafeSubscriber.__tryOrUnsub @ Subscriber.js:234
SafeSubscriber.next @ Subscriber.js:183
Subscriber._next @ Subscriber.js:125
Subscriber.next @ Subscriber.js:89
Subject.next @ Subject.js:55
EventEmitter.emit @ core.es5.js:3834
NgZone.triggerError @ core.es5.js:4205
onHandleError @ core.es5.js:4166
ZoneDelegate.handleError @ zone.js:334
Zone.runTask @ zone.js:169
ZoneTask.invoke @ zone.js:416
Navigated to http://localhost:4200/
core.es5.js:3053Template parse warnings:
The <template> element is deprecated. Use <ng-template> instead ("[WARNING ->]<template><div class="mat-autocomplete-panel" role="listbox" [id]="id" [ngClass]="_getClassList()" #p"): ng:///MdAutocompleteModule/MdAutocomplete.html@0:0
Console.warn @ core.es5.js:3053
TemplateParser.parse @ compiler.es5.js:11508
JitCompiler._compileTemplate @ compiler.es5.js:25195
(anonymous) @ compiler.es5.js:25119
JitCompiler._compileComponents @ compiler.es5.js:25119
createResult @ compiler.es5.js:25004
ZoneDelegate.invoke @ zone.js:330
Zone.run @ zone.js:126
(anonymous) @ zone.js:679
ZoneDelegate.invokeTask @ zone.js:363
Zone.runTask @ zone.js:166
drainMicroTaskQueue @ zone.js:529
api.service.ts:31 undefined "router"

2017-03-26 15_39_04-mtcrm

Activity

  1. DzmitryShylovich commented on Mar 26, 2017

    @DzmitryShylovich
    Contributor

    Please provide a small repro. You can use http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5?p=catalogue as a starting point

  2. ph55 commented on Mar 26, 2017

    @ph55
    Author
  3. Provson commented on Mar 26, 2017

    @Provson

    Same problem in my project

  4. vicb commented on Apr 10, 2017

    @vicb
    Contributor

    The issue is that both ConfigService and Router are eager providers which are initialized during Injector.createInternal():

    AppModuleInjector.prototype.createInternal = function() {
      var self = this;
      //...
      // 1. The injector is not fully initialized when the ConfigService is created
      self._ConfigService_4 = new jit_ConfigService37(self);
      // ...
      // 2. the router is not only initialized after
      self._Router_20 = jit_setupRouter59(self._ApplicationRef_8,self._UrlSerializer_12,self._RouterOutletMap_13,self._Location_16,self,self._NgModuleFactoryLoader_18,self._Compiler_17,self._InjectionToken_ROUTES_19,self._InjectionToken_ROUTER_CONFIGURATION_14,self.parent.get(jit_UrlHandlingStrategy60,null),self.parent.get(jit_RouteReuseStrategy61,null));
    
    }

    injector.get(Router) is called in the constructor of ConfigService before the router service gas been created.

    The returned value is then undefined as the injector provides the Router but it has not been initialized yet.

    Notes:

    • This issue is not related to the Router but is a more general issue,
    • Because more providers are eager now it is more likely to happen,
    • We will work to fix this issue.
  5. changed the title [-]Router not injected as expected[/-] [+]Eager providers and Injector.get() can cause errors[/+] on Apr 10, 2017
  6. removed their assignment
    on Apr 10, 2017
  7. 15 remaining items

  8. added a commit that references this issue on Oct 11, 2017
    e292548
  9. atekien commented on Oct 18, 2017

    @atekien

    Is there any known workaround for this issue?

  10. cedricremond commented on Mar 1, 2018

    @cedricremond

    Still facing the issue (Angular 5.2.0). Any workaround ?

  11. jcqttran commented on Jul 18, 2018

    @jcqttran

    Hi everyone, I'm currently facing this problem, any updates ?
    Thanks

  12. ZbigiMan commented on Oct 9, 2018

    @ZbigiMan

    I have the same problem in Angular 6. Workaround is putting injector.get into setTimeout like Provson did it.

  13. angular-automatic-lock-bot commented on Sep 14, 2019

    @angular-automatic-lock-bot

    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.

  14. locked and limited conversation to collaborators on Sep 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: coreIssues related to the framework runtimefreq2: mediumregressionIndicates than the issue relates to something that worked in a previous versiontype: bug/fix

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions