【问题标题】:How to lazy evaluate merged observable, i.e. on click of button when using merge() (RxJs v6)?如何延迟评估合并的 observable,即使用 merge() (RxJs v6) 时单击按钮?
【发布时间】:2021-06-28 14:25:32
【问题描述】:

我有一个合并的 observable 流,

const nextClickHandler$ = merge(doA$, doB$, doC$),

do A$/B$/C$ 是可观察的,它发出 HTTPRequest 或执行一些副作用,它们在一些互斥条件下运行,其中 doA$/doB$/doC$ 处于活动状态并执行网络调用/副作用。

用例是,在单击下一步按钮时,执行 A/B/C,如果我在单击下一步之前订阅它,我将面临如何订阅此合并的 observable 的问题,即

ngOnInit(){
    this.nextClickHandler$.subscribe()
}

这将急切地评估那些互斥的条件并执行,甚至无需单击下一步,

我尝试点击 goForward 订阅:

 goForward(): void {
        if (this.getCurrentStep() == 1) {
            if (this.validateForm()) {\
                //performs side-effects for either A$/B$/C$
                this.nextClickHandler$.subscribe();  
            }
            return;
        }

但是现在,当我再次进入步骤 I 时,它不会等待点击下一步,因为它是一个长期订阅,它只是急切地执行行为,这不是我想要的,我想要的它们仅在单击下一步时才延迟执行,我尝试了 take(1) 但这并不能解决问题,我该如何实现?

【问题讨论】:

  • 问题:当您在goForward() 中订阅时,它是否有效?所以你的问题是你想在他们回去时取消订阅?
  • 我绝对可以这样做,回去时我可以取消订阅,当我在goForward()订阅时它确实有效,但是有没有比手动管理订阅更好的方法,我不喜欢每次点击下一个就创建订阅的想法。
  • 可能有更好的方法。如果不了解您的流程,很难说。您可能有一个 currentStep$ 可观察对象,它在内部使用 switchMap() 订阅与每个步骤相关的任何可观察对象。如果您分享更多详细信息/代码,我可以详细说明。如果您可以将其放在StackBlitz 中,那将更容易为您提供帮助。 :-)

标签: angular typescript rxjs observable rxjs6


【解决方案1】:

你可以尝试从按钮的点击事件中创建一个 Observable,使用fromEvent:

 <button #sbtn>
      Subscribe
    </button>

 @ViewChild('sbtn', { static: true }) sbtn: ElementRef;
 this.clickBtnEvent$ = fromEvent(this.sbtn.nativeElement, 'click');

然后在初始化时(或在视图初始化之后)订阅该 Observable:

this.clickBtnEvent$.pipe(
  mergeMap(() => nextClickHandler$)
).subscribe( /* some logic*/);

这个 Observable 只会在你点击按钮时发射,实际上是每次你点击它的时候。

【讨论】:

    【解决方案2】:

    如果您不喜欢创建多个订阅变量,那么,

    switchMap() 是一个很好的例子,但如果你想继续使用merge()mergeMap,请尝试使用takeUntil() 运算符。您无需每次都创建订阅变量。

    你只创建一次,销毁一次,但你可以在同一个页面代码中多次使用它。

    // Step-1: Create a destroy variable
    destroy$: Subject<any> = new Subject();
    
    // Step-2: Use it how many times you want
    
    obs1$.pipe(takeUntil(this.destroy$)).subscribe();
    obs2$.pipe(takeUntil(this.destroy$)).subscribe();
    obs3$.pipe(takeUntil(this.destroy$)).subscribe();
    .
    .
    .
    so on... 
    
    // Step-3 : Destroy the subject
    
    ngOnDestroy() {
      this.destroy$.next();
      this.destroy$.complete();
    }
    

    如果你想合并 observables,你也可以使用 combineLatest() 操作符,你可以一次订阅多个 observables。像这样的:

    combineLatest(obs1$, obs2$, obs3$)
       .takeUntil(this.destroy$)
       .subscribe(([obs1Data, obs2Data, obs3Data]) => {})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-09
      • 2014-10-18
      • 1970-01-01
      • 2016-07-15
      • 1970-01-01
      • 1970-01-01
      • 2021-05-17
      • 1970-01-01
      相关资源
      最近更新 更多