网站搜索

angular - BehaviorSubject .next() 没有发出更新的值


我只是想为我对 RxJS 和 Observables 的理解不足道歉。我之前发过一个问题,但表述得很糟糕,我知道别人无法理解,所以过了一天后,我想我可以更好地解释我的问题。

  1. 我的代码目标是获取用户输入,将其作为动作流传递到我的数据流,比对输入与我的泊位数组,如果存在,则返回该单个泊位。如果不存在 (这是我正在挣扎的部分),则返回一个可观察对象,我可以在 bay.page.ts 中回调,并检查它是否为 true 或 false。如果是 false [显示客户端错误]。如果是 true,则导航到结果页面。
  2. 我的 bay-service.ts 类包含我的数据和操作流:
export class BayServiceService {
  private baysUrl = 'api/bays';

  bays$ = this.http.get<Bay[]>(this.baysUrl)
    .pipe(
      tap(data => console.log('Bays: ', JSON.stringify(data))),
      catchError(this.handleError)
    );

  /*--------------------------------------------------------------*/
  // Grab A Single Bay
  private baySelectedSubject = new BehaviorSubject<number>(0);
  baySelectedAction$ = this.baySelectedSubject.asObservable();

  invalidBay = new BehaviorSubject<boolean>(false);

  selectedBay$ = combineLatest([
    this.bays$,
    this.baySelectedAction$
  ])
    .pipe(
      map(([bays, selectedBayNumber]) => {
        if (!bays.find(bay => bay.bayCode === selectedBayNumber)){
          this.invalidBay.next(false);
        } else {
          this.invalidBay.next(true);
          return bays.find(bay => bay.bayCode === selectedBayNumber);
        }
      }),
      );

  selectedBayChanged(selectedBayNumber: number): void {
    this.baySelectedSubject.next(selectedBayNumber);
  }

^在上面的代码中,我使用了声明式的 RxJS 方法 selectedBay$,在其中我将我的 bay$ 数据流和 baySelectedAction$ 操作流(包含用户输入)结合起来。然后我对它们进行映射,并将用户输入的 selectedBayNumber 与单个泊位编号进行比较。

问题:我正在尝试使用 Observable -> invalidBay=new BehaviorSubject<boolean>(false);,这是我在 bay-service.ts 中创建的,并检查它的结果:如果为 true,则向前导航。如果为 false,则显示客户端错误提示,说明它不存在。然而,如果用户输入一个有效的泊位号,我尝试通过 this.invalidBay.next(true); 将该 Observable 改为 true,但是,observable 的值不会更新?BehaviorObservable 保持其默认值 'false'。所以代码部分有效,但不完全。

  1. 这是我在 bay-page.ts 中的 onSubmit 方法,我在这里处理用户输入以进行我的操作流。我将用户输入传递给一个方法(该方法在我的 bay-service.ts 类中)。根据他们的输入,我尝试订阅那个“应该被更新”的 Observable,然后再从那里继续。但这个 Observable 并没有被更新。请帮忙。
onSubmit() {
    this.bayService.selectedBayChanged(this.bayForm.get('bayStart').value);
    this.subscription = this.bayService.invalidBay.subscribe(value => {
        if (value) {
            this.navCtrl.navigateForward([`/results/`]);
        } else {
            this.bayDoesNotExistError = true;
            this.selectedBay = this.bayForm.get('bayStart').value;
            this.vibration.vibrate(500);
            console.log('Vibrating for 3 second...')
        }
    })
}

为什么 Observable 的值没有更新?请帮帮我,我脑袋疼,不知道还能做些什么。

答案#1

如果没有观察者订阅,observable 什么也不会做。你没有订阅 selectedBay$ observable。因此,从 combineLatest 开始的 pipe 中的代码根本不会执行,无论向你的 action 流发射多少新值,你总是会收到 invalidBay 的初始 false 值。

一些建议:

  1. BehaviorSubject 是一个多播的可观察对象,你应该始终将其保持为私有,以最小化对它调用 next() 的范围。使用 .asObservable() 方法将其作为可观察对象暴露,如果任何外部代码需要发出新值的能力,可以提供一个公共方法来实现这一点。你已经以这种方式处理 baySelectedSubject。考虑对 invalidBay 做同样的处理。

  2. 永远不要将你的订阅代码放在会被执行多次的方法中。每次方法执行时,你都会创建一个新的订阅。Observable 会向每个订阅发出值。因此,请将你的订阅从 onSubmit() 中移除,并放到 ngOnInit() 中。

为您服务,更改 -

invalidBay = new BehaviorSubject<boolean>(false);

到

private invalidBay = new BehaviorSubject<boolean>(false);
invalidBay$ = this.invalidBay.asObservable();

在你的组件中 -

ngOnInit(): void {
    this.bayService.selectedBay$.subscribe(
        p => {
            // do something with the Bay value
        }
    );

    this.bayService.invalidBay$.subscribe(
        p => {
            // do something with the invalidBay value
        }
    );
}

onSubmit(): void {
    this.bayService.selectedBayChanged(this.bayForm.get('bayStart').value);
}