简体   繁体   English

如何懒惰地评估合并的 observable,即在使用 merge() (RxJs v6) 时单击按钮?

[英]How to lazy evaluate merged observable, i.e. on click of button when using merge() (RxJs v6)?

I have a merged stream of observables,我有一个合并的 stream 的 observables,

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

do A$/B$/C$ are observables which makes HTTPRequests or performs some sideeffects, they operate on some mutually exclusive conditions, where either doA$/doB$/doC$ are active and perform the network calls / side-effects. do A$/B$/C$是发出 HTTPRequest 或执行某些副作用的可观察对象,它们在某些互斥条件下运行,其中 doA$/doB$/doC$ 处于活动状态并执行网络调用/副作用。

The use-case is, on the click of the next button, do either A/B/C, I am facing an issue on how to subscribe to this merged observable, if I subscribe to it before-click of next, ie用例是,在单击下一步按钮时,执行 A/B/C,如果我在单击下一步之前订阅它,我将面临如何订阅此合并的 observable 的问题,即

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

This will be eagerly evaluating those mutually exclusive conditions and executing, without even clicking next,这将急切地评估那些互斥的条件并执行,甚至无需单击下一步,

I tried subscribing on click of goForward:我尝试点击 goForward 订阅:

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

But now, when I am on the Step I again, it doesnt wait for the click of the next, since it is a long-living subscription, it just eagerly executes the behaviour, which is not what I want, I want them to be lazy-executed only when clicking next, I tried take(1) but that does not fix the issue, How can I achieve this?但是现在,当我再次进入 Step I 时,它不会等待点击下一个,因为它是一个长期订阅,它只是急切地执行行为,这不是我想要的,我希望他们成为仅在单击下一步时才延迟执行,我尝试了take(1)但这并不能解决问题,我该如何实现?

If creating multiple subscription variables is not something to your liking then,如果您不喜欢创建多个订阅变量,

switchMap() is a good example to use, but if you want to keep using merge() or mergeMap , try using takeUntil() operator. switchMap()是一个很好的使用示例,但如果您想继续使用merge()mergeMap ,请尝试使用takeUntil()运算符。 You need not create a subscription variable every time.您无需每次都创建订阅变量。

You create only once and destroy once, but you can use it many times in the same page code.您只创建一次并销毁一次,但您可以在同一页面代码中多次使用它。

// 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();
}

If you want to merge observables, you can also use combineLatest() operator, where you can subscribe to multiple observables at once.如果你想合并 observables,你也可以使用 combineLatest() 操作符,你可以一次订阅多个 observables。 Something like this:像这样的东西:

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

You can try to create an Observable from click event of the button, using fromEvent :您可以尝试使用fromEvent从按钮的单击事件创建一个 Observable :

 <button #sbtn>
      Subscribe
    </button>

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

and than on init (or after view init) you subscribe to that Observable:而不是在 init 上(或在 view init 之后)你订阅了那个 Observable:

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

This Observable will emit only when you click the button, actualy every time you click on it.这个 Observable 只会在你点击按钮时发射,实际上是每次你点击它的时候。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM