асинхронное событие в хуках жизненного цикла - PullRequest
0 голосов
/ 04 мая 2020

У меня есть вопрос об асинхронных событиях (таких как наблюдаемые события) в хуках жизненного цикла.

Если мне нужно извлечь данные из серверной части в ngOnInit, а затем назначить свойство в классе, например:

   data: string;

   ngOnInit() {
     this.httpService.get(...).subscribe(data => this.data = data);
   }

   ngAfgerViewInit() {}

Здесь, поскольку Observable делает функцию обратного вызова, которая будет обрабатываться как событие, и go попадет в очередь стеков событий. Итак, мой вопрос, когда будет выполняться хук ngAfterViewInit ()?

  1. после завершения назначения данных, затем go до следующего перехвата жизненного цикла.
  2. продолжайте до конца sh всех перехватов жизненного цикла, затем выполните присваивание данных.

Какой из них правильный?


Я провел несколько экспериментов. Пожалуйста, смотрите детали ниже. Кстати, я использую выбор магазина ngrx для создания наблюдаемого здесь.

1. Я консоль, чтобы увидеть последовательность выполнения.

мой код:

enter image description here

консоль:

enter image description here

функция обратного вызова выполняется как синхронная, но не выполняется после ngAfterViewInit.

2. Я добавляю еще один оператор ngrx «of» для создания другого Observable в ngOnInit.

код:

enter image description here

консоль:

enter image description here

это то же самое, что и # 1, функция обратного вызова выполняется перед ngAfterViewInit, подобно синхронному.

3. Я добавляю еще один оператор ngrx «таймер» для создания другого Observable в ngOnInit.

код:

enter image description here

консоль:

enter image description here

на этот раз функция обратного вызова выполняется после ngAfterViewInit и обрабатывается как асинхронная.

Так что это меня очень смущает. Некоторые наблюдаемые обрабатываются как асинхронные, а некоторые - как синхронные. Кто-нибудь знает почему?

Ответы [ 3 ]

1 голос
/ 04 мая 2020

Согласно исходному коду Angular, исключение ловушек является синхронным процессом . Это означает, что все перехваты помещаются в callstack и сразу выполняются один за другим.

Создание подписки будет также вызываться внутри callstack this.httpService.get(...).subscribe(...);.

Asyn c характер HTTP-запросов

HttpClient использует XMLHttpRequest под капотом с кодом xhr.addEventListener('load', onLoad);. onLoad - это внутренний обратный вызов, помещенный в очередь обратного вызова и выполненный после того, как запрос завершен, и стек вызовов стал пустым. Этот обратный вызов завершает наблюдаемый с помощью HTTP-запроса и приводит к выполнению обратного вызова из .subscribe(...).

Так что обратный вызов .subscribe(data => this.data = data) помещается в стек вызовов только после того, как angular обрабатывает асинхронный c ответ HTTP-запроса - после всех перехватов.

(Кстати, обратные вызовы выполняются синхронно для потоков с данными syn c (например, of(true).subscribe(...)))

По вашему вопросу порядок выполнения - ngOnInit -> ngAfterViewInit -> callback function.

Но если наблюдаемое имеет данные syn c, например of(true).subscribe(some_callback) - оно будет выполнено с порядком ngOnInit -> callback -> ngAfterViewInit - все синхронно.

Пример https://stackblitz.com/edit/angular-vdwnle

Надеюсь, это поможет.

0 голосов
/ 04 мая 2020

Все события являются асинхронными

Вызывает ваш метод get из службы, затем вызывает код в oninit вне подписки. И после того, как oninit закончен (данные все еще загружаются, и внутренняя подписка не выполняется до сих пор), после запускаInInit выполняется.

И в промежутке времени, когда данные поступают из сервиса, ваша подписка выполняется

проверьте ниже ссылку для получения дополнительной информации https://www.bennadel.com/blog/3071-synchronous-vs-asynchronous-eventemitters-in-angular-2-beta-14.htm

0 голосов
/ 04 мая 2020

Используйте ChangeDetectorRef для вызова следующей ловушки lyfecycle:

  constructor(
    private _cdr: ChangeDetectorRef,
    private httpService: YourHttpService,
  ) {}

  ngOnInit(): void {
    this.httpService.get(...).subscribe(data => {
      this.data = data;
      this._cdr.detectChanges();
    });
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...