更新源Observable时未调用Observable管道

问题描述

我有两个Observables,一个依赖于另一个的数据。

更改第一个Observable上的数据时,应更新第二个Observable。

不幸的是,这无法正常工作。

这是主要的Observable(效果很好)

export class LocaleService {
  locale$: Observable<string>;

  constructor(private router: Router) {
    this.locale$ = router.events.pipe(
      filter(evnt => envt instanceof ActivationEnd),map((evnt: ActivationEnd) => evnt.snapshot.paramMap.get('locale')),shareReplay(1),);
  }
}

这里是第二个Observable,应根据第一个Observable的值(如上所示)进行更新:

// This type is more complex,but made it simple for demonstrating the problem
interface ICountries { code: string; }

export class DataService {
  countries$: Observable<ICountries>;

  constructor(private http: HttpClient,private localService: LocaleService) {
    this.localeService.locale$.subscribe(locale => {
      // this is only here for debug purposes,showing it does change
      console.log('changed locale',locale);
    });

    this.countries$ = localeService.locale$.pipe(
      tap(locale => { console.log('http updated',locale); }),// called first time only,not on locale changes...
      switchMap(locale => this.http.get<ICountries>(`http://localhost:8080/countries?lang=${locale}`)),);
  }
}

如果需要的话,我使用countries$的方式如下(再次简化以演示问题):

@Component({
  template: `<ng-container *ngIf="countries$ | async as countries">{{ countries.code }}</ng-container>`,})
export class CountryComponent implements OnInit {
  countries$: Observable<ICountries>;

  constructor(private dataService: DataService) {
    this.countries$ = dataService.countries$;
  }
}

我已经为此苦苦挣扎了几天,在StackOverflow上寻找答案,在许多其他论坛上问他们,并询问更频繁使用Observables的朋友,但是我似乎无法解决这个问题。任何帮助将不胜感激!

解决方法

我不确定,但是您可以尝试将可观察对象分成两个不同的部分。目前,它像下面的单流

this.countries = localeService.locale$.pipe(
  tap(locale => { console.log('http updated',locale); }),// called first time only,not on locale changes...
  switchMap(locale => this.http.get<ICountries>(`http://localhost:8080/countries?lang=${locale}`)),shareReplay(1),tap(locale => { console.log('http updated',shareReplay(1)
);

这是我的建议。我已经使用ReplaySubject和缓冲区1(与问题中的shareReplay相同)将可观察到的流分为两个不同的流

LocaleService

export class LocaleService {
  localeSource = new ReplaySubject<string>(1);
  locale$ = this.localeSource.asObservable();

  constructor(private router: Router) {
    router.events.pipe(
      filter(evnt => envt instanceof ActivationEnd),map((evnt: ActivationEnd) => evnt.snapshot.paramMap.get('locale'))
    ).subscribe(event => this.localeSource.next(event));
  }
}

DataService

// This type is more complex,but made it simple for demonstrating the problem
interface ICountries { code: string; }

export class DataService {
  countriesSource = new ReplaySubject<ICountries>(1);
  countries$ = this.countriesSource.asObservable();

  constructor(private http: HttpClient,private localeService: LocaleService) {
    this.localeService.locale$.pipe(
      tap(locale => { console.log('http updated',switchMap(locale => this.http.get<ICountries>(`http://localhost:8080/countries?lang=${locale}`))
    ).subscribe(countries => this.countriesSource.next(countries));
  }
}

CountryComponent

@Component({
  template: `<ng-container *ngIf="(countries$ | async) as countries">{{ countries?.code }}</ng-container>`,})
export class CountryComponent implements OnInit {
  countries$: Observable<ICountries>;

  constructor(private dataService: DataService) {
    this.countries$ = this.dataService.countries$;
  }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...