Различия между декларативным и реактивным подходом в приложении Angular - PullRequest
2 голосов
/ 05 февраля 2020

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

Допустим, у меня есть что-то вроде этого: список компонентов, основанных на элементах массива.

<hello *ngFor="let h of helloComponents"></hello>

Привет компонент подписан на BehaviorSubject из службы.

В какой-то момент (например, когда нажата кнопка) смысл поведенияSubject выдает новое значение, но массив также обновляется.

Порядок событий следующий:

  1. субъект выдает новое значение
  2. компоненты, подписанные на субъект, получают новое значение
  3. массив обновляется, новые компоненты инициализируются и получают новое значение в качестве первого значения от субъекта

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

Если я сначала обновлю массив, а затем pu sh новое значение из субъекта, сценарий не изменится.

Я нашел 2 исправления:

A. используйте setTimeout, чтобы быть уверенным, что субъект выдает новое значение, когда старые компоненты уже были уничтожены Angular Обнаружением изменений. Но я не знаю, насколько надежно это решение ...

this.myarray= [4, 5];
setTimeout(() => subject.next(new value));

B. используйте наблюдаем (asyncScheduler)

this.stateService.state$.pipe(
        observeOn(asyncScheduler)
    ).subscribe(
      state => console.log(`helloComponent ${this.id}, state: ${state}`)
    )

но я действительно новичок в Rx js Планировщик, я не знаю, является ли это хорошим подходом или есть лучшая альтернатива.

Вот стекаблиц ... открой консоль

Есть идеи?

1 Ответ

0 голосов
/ 05 февраля 2020

Я использовал отслеживание в сочетании с обнаружением изменений вручную (может показаться грубым, но вы вручную обновляете массив helloComponents в том же событии l oop, что и запуск обновления из службы), и оно, похоже, работает :

import { Component, ChangeDetectorRef } from '@angular/core';
import { StateService } from './state.service';

@Component({
  selector: 'my-app',
  template: `<hello *ngFor="let h of helloComponents, trackBy: trackById" [id]="h"></hello> <button (click)="action()">action</button>`
})
export class AppComponent {
  name = 'Angular';
  helloComponents = [1, 2, 3];

constructor(private stateService: StateService, private ref: ChangeDetectorRef) {}

  action() {
    this.helloComponents = [4, 5];
    this.ref.detectChanges();
    this.stateService.action();
  }

  trackById = id => id;
}

stackblitz: https://stackblitz.com/edit/angular-e9zfoq?file=src / app / app.component.ts

...