Angular 2 ngOnInit вызывается дважды с ошибкой

#angular #typescript

#angular #typescript

Вопрос:

Я столкнулся со странной ошибкой в Angular 2. У меня есть два похожих компонента с похожими шаблонами и похожими сервисами. Вот основы того, как они работают:

Компонент:

 theData: any;

constructor(private _theService: TheService) {}

ngOnInit() {
    this._theService.getData()
        .subscribe(data => {
            this.theData = data;
        });
}
  

Обслуживание:

 private _url = "http://url.net/api/Data";

constructor(private _http: Http) {
}

getData() {
    return this._http.get(this._url)
        .map(res => res.json());
}
  

это возвращает массив объектов, например:

 [
    {name: "Name 1"},
    {name: "Name 2"}
]
  

и шаблон отображает их следующим образом:

 <div *ngFor="let item of theData">{{ item.name }}</div>
  

Затем вы можете щелкнуть элемент, где вы попадаете на страницу, которая следует той же стратегии, что и выше, за исключением того, что service / api возвращает только один объект, а шаблон не использует *ngFor, потому что для отображения требуется только один элемент.

Итак, это выглядит так:

 theItem = {name: "Name 1"} // what the service returns

<div>{{ theItem.name }}</div>
  

Все отлично работает при отображении всех элементов, но когда я нажимаю на отдельные элементы, OnInit вызывается дважды, и я получаю сообщение об ошибке в platform-browser.umd.js что на самом деле является ошибкой в шаблоне, потому что в нем говорится, что он не может прочитать свойство name undefined (которое является элементом).

Я решил эту проблему, изменив шаблон для отдельных элементов на:

 <div>{{ theItem?.name }}</div>
  

Сначала я подумал, что проблема заключалась в том, что шаблон отображался до загрузки данных из службы, поэтому добавление ? исправило это. Но разве шаблон не должен загружаться ПОСЛЕ завершения ngOnInit? Мой вопрос в том, почему добавление ? исправило эту проблему, хотя мне это не нужно в первом шаблоне при загрузке всех элементов?

Спасибо.

Ответ №1:

Поскольку get он асинхронный, он фактически начинает отображать шаблон до загрузки данных. Он завершит вызов службы и не будет ждать, он продолжит обработку. Добавление ? позволяет ему быть undefined , а затем отображать соответствующим образом после загрузки данных.

Комментарии:

1. Хорошо, значит, единственная причина, по которой это работает в первом сценарии, заключается в том, что служба возвращает данные достаточно быстро, а шаблон еще не был отрисован?

2. или *ngFor обрабатывает его как неопределенный, тогда как прямая ссылка на объект этого не делает. Честно говоря, я не уверен, я никогда не углублялся в этот сценарий

3. Да, мне было интересно, было ли это *ngFor для его обработки, и я думаю, что это так. Я сообщу, если найду что-нибудь еще по этому поводу. Спасибо!

4. Получил ту же проблему слово в слово. Другой способ решить эту проблему — использовать *ngIf="theItem" в корневом узле шаблона. Это позволяет избежать использования ? при каждой привязке. Мои предыдущие шаблоны работали нормально, потому что они уже его использовали. Кроме того, обратите внимание, что я столкнулся с этой проблемой, потому что мой компонент использует параметры маршрута, которые извлекаются из ActivatedRoute через Observable , поэтому, я думаю, почему «задержка».