[英]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.