Observable / BehaviorSubject не работает в разных модулях Angular

#javascript #angular #observable #angular10 #behaviorsubject

#javascript #angular #наблюдаемый #angular10 #behaviorsubject

Вопрос:

У меня есть 1 функциональный модуль ( Fund module ), который отображает данные фонда в одном из его компонентов, и AppModule который отображает данные советника. Данные фонда и данные советника имеют отношение один ко многим. Компонент Fund получает данные из сервисов, определенных в AppModule.

Данные передаются в модуль Fund с использованием BehaviorSubject as data, который может измениться, если пользователь обновит или изменит данные в AppModule. Подписка на данные работает некорректно. Модуль fund отображает только значение (10), с которым BehaviorSubject инициализируется. Он не отображает обновленное значение (100), и подписка не работает должным образом для отображения значений во второй раз.

Вот код:

Сервис в AppModule:

 test = new BehaviorSubject<number>(10);

getTest(): Observable<number> {
  return this.test.asObservable();
}

public updateLocalData(sleeves: Sleeve[]): void {
  .... update logic
  this.test.next(100);
}
 

FundDataComponent в модуле Fund

 changeDetection: ChangeDetectionStrategy.OnPush,

   ngOnInit(): void {
    this.test = this.service.getTest().subscribe((number) => {
      this.number = number;
      console.log(number);    // get's called only once to display 10
    });
  }
 

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

1. Загружается ли модуль fund лениво?

2. Где вы вызываете updateLocalData?

3. @korteee нет, он не загружается лениво

4. @WillAlexander Я вызываю updateLocalData в одном из компонентов (EditDataComponent) в AppModule

5. не могли бы вы воспроизвести это на stackblitz?

Ответ №1:

Создайте model — resource.ts:

 import { BehaviorSubject, Observable } from 'rxjs';
import { refCount, publishReplay } from 'rxjs/operators';

export class StreamResource {
   private loading = false;
   private behaviorSubject: BehaviorSubject<any>;
   public readonly obs: Observable<any>;

   constructor(defaultValue?: any) {
       this.behaviorSubject = new BehaviorSubject(defaultValue);
       this.obs = this.behaviorSubject.asObservable().pipe(publishReplay(1), refCount());
   }

   request(method: any): void {
       if (method amp;amp; !this.loading) {
           this.loading = true;
           method().toPromise().then((data: any) => {
               if (data) { this.update(data); }
               this.loading = false;
           });
       }
   }

   getValue() {
       return this.behaviorSubject.getValue();
   }

   update(data: any) {
       this.behaviorSubject.next(data);
   }

   refresh() {
       const data = this.getValue();
       if (data) { this.update(data); }
   }
}
 

Создайте StreamService

 import { StreamResource } from '../models/resource';
public test = new StreamResource(10);

...

getTest() {
    this.test.request(() => this.testService.getTest());
}

 

Как использовать?

   constructor(private streamService: StreamService) { }

  ngOnInit() {
    this.streamService.test.obs.subscribe((data: any) => {
      if (!data) {
        return this.streamService.getTest();
      } else {
        this.test = data;
      }
    });
 

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

1. @PritamBohra github.com/dm-grinko/angular-rxjs-template