Angular BehaviorSubject.next()未发出更新的值

Angular BehaviorSubject.next()未发出更新的值,angular,typescript,rxjs,rxjs6,rxjs-observables,Angular,Typescript,Rxjs,Rxjs6,Rxjs Observables,我只是想为我对RxJS和可观测数据缺乏理解而道歉。我之前发布了一个问题,但措辞非常糟糕,我知道这是不可理解的,所以一天后我想我可以更好地解释我的问题 我的代码的目标是获取用户输入,将其作为操作流传递给我的数据流,将输入与我的间隔数组进行比较,如果存在,则返回单个间隔。如果它不存在(这是我正在努力的地方)返回一个可观察到的,我可以在我的bay.page.ts中调用它,并检查它的是否为true或false。如果为假[显示客户端错误]。 如果是true,则向前导航到结果页面 Mybay service

我只是想为我对RxJS和可观测数据缺乏理解而道歉。我之前发布了一个问题,但措辞非常糟糕,我知道这是不可理解的,所以一天后我想我可以更好地解释我的问题

  • 我的代码的目标是获取用户输入,将其作为操作流传递给我的数据流,将输入与我的间隔数组进行比较,如果存在,则返回单个间隔。如果它不存在(这是我正在努力的地方)返回一个可观察到的,我可以在我的
    bay.page.ts
    中调用它,并检查它的
    是否为true
    false
    。如果为假[显示客户端错误]。 如果是
    true
    ,则向前导航到结果页面
  • My
    bay service.ts
    类包含我的数据和操作流:

  • 为什么观察对象的值没有更新?求你了,我的心很痛,我不知道还能做什么。

    如果没有观察者订阅,一个可观察者什么也不做。您没有订阅
    selectedBay$
    observable。因此,来自
    combinelateest
    的管道中的代码根本不会执行,不管新值被发送到动作流多少次,并且您总是从
    invalidBay
    接收初始
    false

    一些建议:

  • BehaviorSubject
    是一个可观察的多播对象,您应该始终保持它的私有性,以最小化对它调用
    next()
    的范围。使用
    .asObservable()
    方法将其公开为可观察,如果任何外部代码需要发出新值的能力,请提供一个公共方法。您已经以这种方式处理了
    baySelectedSubject
    。考虑对<代码> SimuldBuy.P/>进行同样的操作。
  • 切勿将订阅代码放入将执行多次的方法中。每次执行该方法时,您都将创建一个新订阅。可观察对象将向每个订阅发送值。因此,从
    onSubmit()
    中删除订阅并将其放入
    ngOnInit()

  • 如果您没有使用它,请避免存储
    订阅
    引用。您只需按以下方式订阅-

  • this.bayService.invalidBay$.subscribe(值=>。。。
    
    而不是-

    this.subscription=this.bayService.invalidBay.subscription(值=>。。。
    
    如果确实需要
    Subscription
    引用,请记住在
    ngondstroy
    方法中进行清理-

    ngondestory():void{
    this.subscription.unsubscripte();
    }
    
    这将在组件被销毁后立即取消对可观察对象的订阅。否则,
    订阅
    引用将保留可观察对象,即使在组件被销毁后,这将最终导致内存泄漏

    根据建议(相对)更好地实施:

    服务-

    导出类BayServiceService{
    私有baysUrl=‘api/bays’;
    bays$=this.http.get(this.baysUrl)
    .烟斗(
    点击(data=>console.log('Bays:',JSON.stringify(data)),
    catchError(this.handleError)
    );
    private baySelectedSubject=新行为主体(0);
    baySelectedAction$=this.baySelectedSubject.asObservable();
    private invalidBay=新行为主体(false);
    invalidBay$=this.invalidBay.asObservable();
    selectedBay$=CombineTest([this.bays$,this.baySelectedAction$]))
    .烟斗(
    地图(([bays,selectedBayNumber])=>{
    让bay=bays.find(p=>p.bayCode===selectedBayNumber);
    如果(!间隔){
    this.invaliday.next(false);
    }否则{
    this.invaliday.next(true);
    返回湾;
    }
    }));
    selectedBayChanged(selectedBayNumber:number):无效{
    this.baySelectedSubject.next(selectedBayNumber);
    }
    }
    
    在您的组件中-

    ngOnInit():void{
    此.bayService.selectedBay$.subscribe(
    p=>{
    //用间隔值做点什么
    }
    );
    此.bayService.invaliday$.subscribe(
    p=>{
    //用invalidBay值做一些事情
    }
    );
    }
    onSubmit():void{
    this.bayService.selectedBayChanged(this.bayForm.get('bayStart').value);
    }
    ngOnDestroy():void{
    //如果您存储了订阅引用
    this.subscription.unsubscripte();
    }
    
    Wow,我真的很感谢这些建议,我同意他们!但是,我不想在我的ngOnInit中使用
    this.bayService.invalidBay$.subscribe
    ,因为每次运行这段代码时都应该更新它:
    this.bayService.selectedBayChanged(this.baysform.get('bayStart').value)
    这将在用户提交时发生。这段代码将触发selectedBay$,并根据用户的输入触发invalidBay$observable以发出一个值。但事实并非如此,它只是false。我想处理该observable的值,如果为false,则抛出客户端错误,或者向前移动。@Donnygroezinger需要从
    invalidBay$
    更新的值,而不是新订阅。将订阅代码放入
    ngOnInit
    中,您仍将在任何时候收到更新的发射。下一步()在服务中的
    invalidBay
    上被调用。这就是可观察对象的工作方式。测试我在答案中实现的版本,你就会明白。我做了,我正在尝试听你说。我不想要
    this.bayService.selectedBay$.subscribe()
    在这个文件上,因为我已经在我的结果页面中声明了它,它将返回一个选定的间隔。我只希望
    this.bayService.invalidBay$
    结果发出一个false或true。并在submit上处理它。
    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);
      }