Angular 2.1.2/2.2.0 依赖注入实例未定义

Angular 2.1.2/2.2.0 dependency injection instance undefined

在将我的代码从 RC4 迁移到 2.1.2 的过程中,我遇到了一个奇怪的问题:我所有的构造函数参数都未定义它们的值。

我试图将提供程序从组件移动到 app.module.ts 再到 app.component.ts。 None 其中有效。

2.1.2 中的新功能可以使依赖项注入器注入 "undefined" 而不是 creating/providing 服务实例?

备注

  1. 为了使事情更简单,我将代码更改为以下内容
  2. 没有错误信息。
  3. 如果我不将 @Injectable() 添加到 AppComponent 我会得到 Can't resovle all parameters for AppComponent (?,?,?)
  4. 请注意,根注入器未能同时创建用户服务和路由器实例来提供 AppComponent 构造函数。
  5. AuthService 曾经用于注入 Http,但我将其与其他代码一起删除,这样拼图的变数就更少了。
  6. 在Angular 2.2.0 中试过,也不行。

还有什么意见吗?

app.component.ts

import { Component,Injectable }       from '@angular/core'; 
import { Router  } from '@angular/router'; 
import { AuthService }  from '../login/auth.service';

@Component({
  selector: 'my-app',
  template: `
    <h1 class="title">Angular Router</h1>
    <nav>
    </nav>
    <router-outlet></router-outlet>
  `
})
@Injectable()
export class AppComponent {
  constructor(                            // debug here
              private auth: AuthService,  // auth = undefined
              private router: Router,     // router = undefined
              ) {
                console.log("AppComponent constructor");
              }  
}

app.module.ts

import { NgModule }       from '@angular/core';
import { BrowserModule }  from '@angular/platform-browser';
import { FormsModule }    from '@angular/forms';
import { RouterModule }   from '@angular/router';

import { AppComponent }         from './app.component';
import { AuthService }  from '../login/auth.service';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot([
      { path: '', component: AppComponent },
    ])
  ],
  declarations: [ AppComponent ],
  exports: [RouterModule],
  providers:[AuthService ],
  bootstrap: [ AppComponent ]
})
export class AppModule {}

auth.service.ts

import {Injectable} from '@angular/core';

@Injectable()
export class AuthService {  // the debugger can get to this line but never hit constructor
  private _baseUrl: string;
  loggedIn: boolean = false;
  redirectUrl: string;

  constructor() {
    console.log("AuthService constuctor");
    this.loggedIn = !!sessionStorage.getItem('auth_token');
  }

}

main.ts

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './appShell/app.module';
platformBrowserDynamic().bootstrapModule(AppModule);

systemjs.config.js

(function(global) {

  var ngVer = '@2.1.2'; // lock in the angular package version; do not let it float to current!
  var routerVer = '@3.1.2'; // lock router version

  //map tells the System loader where to look for things
  var  map = {
    'app':                        'app',

    // angular bundles
    '@angular/core': 'https://npmcdn.com/@angular/core' + ngVer,
    '@angular/common': 'https://npmcdn.com/@angular/common' + ngVer,
    '@angular/compiler': 'https://npmcdn.com/@angular/compiler' + ngVer,
    '@angular/platform-browser': 'https://npmcdn.com/@angular/platform-browser' + ngVer,
    '@angular/platform-browser-dynamic': 'https://npmcdn.com/@angular/platform-browser-dynamic' + ngVer,
    '@angular/http': 'https://npmcdn.com/@angular/http' + ngVer,
    '@angular/router': 'https://npmcdn.com/@angular/router' + routerVer,
    '@angular/forms': 'https://npmcdn.com/@angular/forms' + ngVer,
    '@angular/upgrade': 'https://npmcdn.com/@angular/upgrade' + ngVer,

    // Other libraries
    'rxjs':                       'https://npmcdn.com/rxjs@5.0.0-beta.12',
    'angular-in-memory-web-api':  'https://npmcdn.com/angular-in-memory-web-api', // get latest
    'ts':                         'https://npmcdn.com/plugin-typescript@4.0.10/lib/plugin.js',
    'typescript':                 'https://npmcdn.com/typescript@2.0.3/lib/typescript.js',

 };

  //packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'main.ts',  defaultExtension: 'ts' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
  };    
  var config = {
    // DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
    transpiler: 'ts',
    meta: {
      'typescript': {
        "exports": "ts"
      }
    },
    map: map,
    packages: packages
  };
  System.config(config);
})(this);

package.json

{
  "name": "TestApp",
  "version": "1.0.0",
  "scripts": {
    "start": "tsc && concurrently \"tsc -w\" \"lite-server\" ",
    "lite": "lite-server",
    "tsc": "tsc",
    "tsc:w": "tsc -w"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@angular/common": "~2.1.2",
    "@angular/compiler": "~2.1.2",
    "@angular/core": "~2.1.2",
    "@angular/forms": "~2.1.2",
    "@angular/http": "~2.1.2",
    "@angular/platform-browser": "~2.1.2",
    "@angular/platform-browser-dynamic": "~2.1.2",
    "@angular/router": "~3.1.2",
    "@angular/upgrade": "~2.1.2",

    "angular-in-memory-web-api": "~0.1.13",
    "core-js": "^2.4.1",
    "reflect-metadata": "^0.1.8",
    "rxjs": "5.0.0-beta.12",
    "systemjs": "0.19.40",
    "zone.js": "^0.6.26"
  },
  "devDependencies": {
    "@types/core-js": "^0.9.34",
    "@types/node": "^6.0.46",
    "concurrently": "^3.1.0",
    "lite-server": "^2.2.2",
    "typescript": "^2.0.3"
  },
  "repository": {}
}

在 RC.5 中 @NgModule was introduced
您需要像这样声明额外的服务、模块等:

import {NgModule} from '@angular/core';
import {LoginComponent} from './login.component';
import {Router,RouterModule} from '@angular/router';
import {FormsModule, FormBuilder} from '@angular/forms';
import {AuthService} from './auth.service';
import {routing} from './app.routing.module';
import {MainComponent} from './main.component';

@NgModule({
  declarations: [LoginComponent], // specify your components here
  imports: [BrowserModule, FormsModule, RouterModule.forRoot([...]), routing],
  providers: [FormBuilder, AuthService, ...], // additional providers
  bootstrap: [MainComponent],
})
class AppModule {}

More info

终于找到了。在 systemjs.config.js 中添加以下内容,效果很好。

typescriptOptions: {
  emitDecoratorMetadata: true
},

我有一点建议。尽量不要在组件上使用 @Injector 装饰器,而是定义一个服务并在那里使用它。它使您的代码更具可读性。