Получение данных от HTTP-запроса до поздней стадии - PullRequest
0 голосов
/ 27 июня 2019

У меня есть служба, где создаются http-запросы для субъекта и поведения субъекта. Затем я получаю данные из сервиса в page.ts (в конструкторе) для отображения в шаблоне.

Код, который я сделал, работает хорошо, но проблема в том, что шаблон "выкрикивает", что данные от субъекта еще не получены. Поэтому выдает ошибку, если я хочу использовать его для инициализации элемента управления FORM или для отображения данных из массива.

PS: Я попробовал с субъектом поведение объекта, и у меня та же проблема. :( Я уверен, что я делаю ошибку зачатия.

Кто-то имеет представление о том, как получить данные до отображения шаблона?

Спасибо за вашу помощь

Сервисный код с субъектом и с поведением субъекта:

const INTI_DATA = [];

@Injectable({
  providedIn: 'root'
})
export class FormStorageService {
  dbSubject = new Subject<any[]>();
  dbBSubject = new BehaviorSubject(INTI_DATA);
  data$: Observable<any> = this.dbBSubject.asObservable();

  private _URL: any = '../assets/DB-Test/data.json';


  private dbData: any[] = [];

  constructor(private http: HttpClient) {}


  getDBDataBehavior() {
    this.http.get<any[]>(this._URL).subscribe((response: any[]) => {
      const value = response['DB_DATA'];
      this.dbBSubject.next(value);
    }, error => {
      console.log('Error : ', error);
      alert(error.message);
    });
  }

  getDBData() {
    this.http.get<any[]>(this._URL).subscribe((response: any[]) => {
      const value = response['DB_DATA'];
      this.dbSubject.next(value);
    }, error => {
      console.log('Error : ', error);
      alert(error.message);
    });
  }
}

Page.TS (Form2Page) с предметным вызовом

export class Form2Page implements OnInit, OnDestroy {
  obsSubscription: Subscription;
  public dbData: DataModel[] = [];

  itemsForm: FormGroup;

  constructor(private storageService: FormStorageService) {
    // Get data from DB
    this.storageService.getDBData();
    this.obsSubscription = this.storageService.dbSubject.subscribe(
      (value: any[]) => {
        this.dbData = value;
        console.log('Value in FORM2 : ', value);
        console.log('DB Data in FORM2 in subscribe : ', this.dbData);
      },
      error => {
        console.log('erreur', error);
      }
    );
    console.log('DB Data DB Data in FORM2 : ', this.dbData);
  }

  ngOnInit() {
    console.log('DB Data in FORM2 in ngOnInit : ', this.dbData);
  }

  ngOnDestroy() {
    this.obsSubscription.unsubscribe();
  }
}

Результат в консоли. Вы можете видеть, что dbData через некоторое время получает некоторые данные

DB Data DB Data in FORM2 :  []
form2.page.ts:46 DB Data in FORM2 in ngOnInit :  []
form2.page.ts:29 Value in FORM2 :  {ITEMS: Array(1)}
form2.page.ts:30 DB Data in FORM2 in subscribe :  {ITEMS: Array(1)}

Page.TS (Form3Page) с вызовом BehaviorSubject

export class Form3Page implements OnInit {
  obsBSubject$ = this.formStorage.data$;
  public dbData: any[] = [];

  constructor(private formStorage: FormStorageService) { 
    this.formStorage.getDBDataBehavior();
    this.obsBSubject$.subscribe(
      (value: any[]) => {
        this.dbData = value;
        console.log('Value in FORM3 : ', value);
        console.log('DB Data in FORM3 in subscribe : ', this.dbData);
      },
      error => {
        console.log('erreur', error);
      }
    );
    console.log('DB Data in FORM3 : ', this.dbData);
  }


  ngOnInit() {
    console.log('DB Data in FORM3 in ngOnInit : ', this.dbData);
  }

}

Результат в консоли. Вы можете видеть, что dbData через некоторое время получает некоторые данные

Value in FORM3 :  []
form3.page.ts:19 DB Data in FORM3 in subscribe :  []
form3.page.ts:25 DB Data in FORM3 :  []
form3.page.ts:30 DB Data in FORM3 in ngOnInit :  []

form3.page.ts:18 Value in FORM3 :  {ITEMS: Array(1)}
form3.page.ts:19 DB Data in FORM3 in subscribe :  {ITEMS: Array(1)}

Ответы [ 3 ]

1 голос
/ 27 июня 2019

Прежде всего вы должны получить данные из вызывающего метода службы в ngOninit, а не в конструкторе. Посмотрите на эту ссылку [ Разница между Конструктором и ngOnInit

, а затем перед отображением всех данных в шаблоне, который вынеобходимо убедиться, что данные уже существуют, используя * ngIf

для обхода решения, если вас не волнует производительность, используйте функцию setTimeOut, но лично я не предпочитаю этот sol ...

1 голос
/ 27 июня 2019

Вы можете использовать * ngIf, чтобы проверить, получили ли данные внешний интерфейс или нет

*ngIf=="data"

Также вы можете проверить, является ли длина больше нуля, с помощью другого div с помощью * ngIf, чтобы сообщить, чтоданные уже попали сюда НО без записей ...

0 голосов
/ 27 июня 2019

В вашем коде и логике я заметил пару проблем.

  1. ngOnInit обычно используется для всей инициализации / объявления.Лучше избегать размещения логики в конструкторе.Конструктор должен использоваться только для инициализации членов класса, но не должен выполнять «работу».Поэтому я бы посоветовал вам переместить логику из конструктора в ngOnInit()

  2. Вы не видите данные в консоли, потому что поток асинхронный.Таким образом, ваши журналы отображаются в консоли до того, как this.dbdata действительно получит значение.

  3. По причине, указанной в пункте 2, если вы попытаетесь создать форму в той же строке, что ина вашей консоли вы получите сообщение об ошибке, так как нет данных.Вместо этого вы должны создать форму после получения данных в методе подписки.

Page.TS (Form3Page) с вызовом BehaviorSubject

export class Form3Page implements OnInit {
  obsBSubject$ = this.formStorage.data$;
  public dbData: any[] = [];

  constructor(
    private formStorage: FormStorageService
  ) { }

  ngOnInit() {
    this.formStorage.getDBDataBehavior();
    this.obsBSubject$.subscribe(
      (value: any[]) => {
        this.dbData = value;
        this.createForm();
        ...
      },
      error => {
        console.log('erreur', error);
      }
    );
  }

  createForm() {
    // Create form here
  }
}
...