Как исправить Angular 2 `Uncaught (in prom): TypeError: Не удается прочитать запрос свойства null??

Я использовал учебник Heroes в Angular 2 документах для экспериментов. Однако я пришел к выводу, что не понимаю, что происходит с этой ошибкой:

Uncaught (in promise): TypeError: Cannot read property 'query' of null в browser_adapter.ts:88.

Две части включают HeroDetailComponent и HeroService.

import { Component, OnInit } from '@angular/core'; 
import { RouteParams } from '@angular/router-deprecated';

import { Hero, HeroService } from '../index';

@Component({
    selector: 'my-hero-detail',
    templateUrl: ...
    styleUrls: [...]
})
export class HeroDetailComponent implements OnInit {

    hero: Hero;

    // TEMPORARY FIX:
    _heroService = new HeroService();  // Avoids injection

    // constructor(private _heroService: HeroService,
    //             private _routeParams: RouteParams) {}

    constructor(private _routeParams: RouteParams) {}

    ngOnInit() {
        let id = +this._routeParams.get('id');
        console.log(id);
    }
}

Когда я использую этот код, он работает. Но когда я переключаю конструкторы и использую одно с вставкой HeroService, то я получаю ошибку, о которой я упоминал ранее.

@Injectable()
export class HeroService {

    getHeroes() {
        return HEROES;
    }

    getHero(id: number) {
        return new Hero(1, 'Name', 'Power', 'AlterEgo');
    }
}

Пока я пытался выяснить, что происходит, я удалил весь код, связанный с обещаниями. Тем не менее, я по-прежнему получаю ту же ошибку. Все компилируется отлично, это ошибка времени выполнения. HeroService и RouteParams предоставляются в родительском компоненте.

Два вопроса:

  • Как решить эту проблему?
  • Как отлаживать такие проблемы?

Я склонен думать, что это ошибка в Angular 2, но я не уверен, как убедиться, что это не ошибка с моей стороны. Спасибо заранее.

ОБНОВЛЕНИЕ:

  • Я добавил код временного исправления (который позволяет избежать инъекций и, следовательно, не является решением этого вопроса, поскольку я хотел бы, чтобы инъекция работала должным образом).

  • Это Plunker с приблизительной версией кода, который я пытаюсь. Я не мог заставить его работать правильно, но может быть полезно диагностировать проблему, просмотрев код.

Ответ 1

Я вижу следующую проблему: HeroComponent зависит от HeroDetailsComponent, но HeroDetailsComponent экспортируется впоследствии в файле app/heroes/index.ts.

Кто-то сообщил о проблеме с таким видом здесь

Ответ 2

В "tsconfig.json" установите параметр "emitDecoratorMetadata" раздела "compilerOptions" в значение "true".

Ответ 3

Я получил эту ошибку с angular RC1, когда я ввел FormBuilder внутри конструктора следующим образом:

export class App {
  constructor(public formBuilder: FormBuilder) {}
}

Но я раньше этого не делал import! Просто добавьте его, решив проблему:

import { FormBuilder } from '@angular/common'

Ответ 4

Попробуйте использовать эти compilerOptions в "tsconfig.json". Он работал у меня (версия 2.0.0-rc.1 из angular).

"compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "declaration": false,
    "noImplicitAny": false,
    "removeComments": true,
    "noLib": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true   },

У меня была та же проблема с инъекциями (такая же ошибка), и исправление делало трюк для служб, но не для http. Я изменил свои параметры на основе учебника от ng-book2, и он наконец-то сработал.

Ответ 5

В моем случае я исправляю эту проблему, используя @Inject decorator. Попробуйте следующее:

import {Inject} from '@angular/core'

constructor(@Inject(HeroService) private _heroService: HeroService,
            @Inject(RouteParams) private _routeParams: RouteParams) {}

Мой проект настроен на JSPM, и это единственный способ работать с инъекцией зависимостей, я не понимаю, у кого есть объяснение?

Отредактировано: Я нашел решение. В моем случае я должен добавить эту конфигурацию в файл config.js

System.config({
 baseURL: "",
 defaultJSExtensions: true,
 transpiler: "typescript",
 typescriptOptions: {
    "target": "es5",
    "emitDecoratorMetadata": true
 },
 paths: {
    "npm:*": "jspm_packages/npm/*",
 ....

Теперь я могу удалить декоратор @Inject, и это предложение работает правильно

constructor(private _heroService: HeroService,
            private _routeParams: RouteParams) {}

Ключ emitDecoratorMetadata: true

Ответ 6

Правильный ответ с RC1 заключается в том, чтобы добавить @Inject(Service) private service:Service, где бы вы не вводили инъекции.

Это не вызвало у меня головной боли после того, как я обновился в понедельник до RC1.