Angular: получение данных из асинхронного режима; Я не должен был форсировать обнаружение изменений - PullRequest
2 голосов
/ 26 апреля 2020

У меня эта проблема слишком часто. Попытка получить список пользователей (из базы данных) и показать их в

user-admin.component. html:

<div class="col-md-2 offset-1">
    <select size=20 [ngStyle]="{'width': '200px'}"> 
      <option *ngFor="let name of userNames">{{name}}</option>
    </select>
</div>

user-admin.component.ts

  userNames: string[] = [];

  constructor(private fb: FormBuilder,
              private authService: AuthService
              ) { }

  ngOnInit() {
    this.authService.getAllUserNames(this.userNames);

getAllUserNames - это функция в сервисе: authService.

  getAllUserNames(userNames: string[]) {
    this.http.get(this.baseUrl + 'usernames').subscribe( (results: string[]) => {
      userNames = results;
    });
  }

Когда страница запускается (ngOnInit) и эта функция вызывается, она корректно возвращает 'userNames' со списком из двух имен пользователей.
enter image description here

Я могу только предположить, что userNames user-admin.component имеет тот же список. (Я проверил html, чтобы убедиться, что в нем будут перечислены имена, если они есть в списке).

Решение? Я предполагаю, что мне нужно вызвать ChangeDetection, и это действительно не кажется необходимым?

ИЛИ this.userNames должен быть ссылочной переменной. Я думал, что это уже (список типов строк). Я попытался создать класс только с this.userName в качестве единственного содержимого, а затем передал класс 'new AllUsers', но список внутри AllUsers также не отображался с именами пользователей.

Идеи? Заранее спасибо. Йог.

Ответы [ 2 ]

2 голосов
/ 26 апреля 2020

Необходимо вернуть наблюдаемое, возвращаемое из HTTP-запроса в сервисе и подписать на него компонент. Попробуйте следующее

user-admin.component.ts

userNames: string[] = [];

constructor(private fb: FormBuilder, private authService: AuthService) { }

ngOnInit() {
  this.authService.getAllUserNames().subscribe(
    response => { this.userNames = response },
    error => { // handle error }
  );
}

authService

getAllUserNames(): Obserable<any> {
  return this.http.get(this.baseUrl + 'usernames');
}

Другим способом будет использование async pipe где вам не обязательно подписываться на компонент. Но это не имеет большого значения в этом сценарии, поскольку async обычно помогает в обработке ошибок утечки памяти. И здесь клиент HTTP заботится о проблемах утечки памяти, поэтому нам не нужно вручную отписываться в компоненте.

Однако, если вы используете пользовательский определенный Observable и wi sh для подписки на него в компоненте, рекомендуется отменить подписку в хуке OnDestroy.

import { Component, OnInit, OnDestroy } from '@angular/core';

export class AppComponent implements OnInit, OnDestroy {
  private subscription: any;

  ngOnInit() {
    this.subscription = this.service.getObservable().subscribe(
      value => { },
      error => { }
    );
  }

  ngOnDestroy() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }
}
0 голосов
/ 26 апреля 2020

вам не нужно подписываться на сервис вместо подписки на класс компонента. Таким образом, вам не нужно форсировать обнаружение изменений. Как только вы обновите userNames (свойство класса компонента), он автоматически отобразится.

user-admin.component.ts

  userNames: string[] = [];

  constructor(private fb: FormBuilder,
              private authService: AuthService
              ) { }

  ngOnInit() {
    this.authService.getAllUserNames().subscribe( (results: string[]) => {
      userNames = results;
    });
}

  getAllUserNames(userNames: string[]) {
    this.http.get(this.baseUrl + 'usernames');
  }
...