I have a component with 2 inputs (or mor) and I want to:
<some-cmp [itemid]="activeItemId$ | async" [userId]="activeUserId$ | async"></some-cmp>
Both values can change at any time, so I figured using rxjs
to build a stream lets me control everything. My current solution seems a bit hacky and is difficult to test. I use 2 BehaviourSubjects
and combineLatest
with a debounceTime
.
@Input() set itemId (id){this.itemId$.next(id)};
@Input() set userId (id){this.userId$.next(id)};
itemId$ = new BehaviourSubject$(null);
userId$ = new BehaviourSubbject$(null);
ngOnInt(){
combineLatest([
this.itemId$.pipe(filter(item=>item!===null)),
this.userId$.pipe(filter(item=>item!===null))
]).pipe(
debounceTime(10),
switchMap(...)
).subscribe(...)
}
So my question are
debounceTime
, which makes testing difficult?The debounceTime
is used in case both value do arrive at the same time and I don't want combineLatest
to trigger the method twice.
You are right in using combineLatest
, it will only emit the first time after each source has emitted once and then will emit any time any source emits.
Is there a way to avoid the debounceTime. [It] is used in case both value do arrive at the same time and I don't want combineLatest to trigger the method twice.
Maybe debounceTime
isn't necessary due to the initial behavior of combineLatest
; it will not emit the first time until all sources emit. However if you typically receive subsequent emissions from both sources that occur within a short timeframe, use of debounceTime
may be an appropriate optimization.
Is there a more elegant way to achieve this behavior?
I think your code is fine. However, it may not be necessary to use BehaviorSubject
since you aren't really using the default value. You could use plain Subject
or ReplaySubject(1)
.
You could assign the result of your combineLatest
to another variable and subscribe to that inside ngOnInit
or use the async
pipe in the template:
@Input() set itemId (id){ this.itemId$.next(id) };
@Input() set userId (id){ this.userId$.next(id) };
itemId$ = new Subject<string>();
userId$ = new Subject<string>();
data$ = combineLatest([
this.itemId$.pipe(filter(i => !!i)),
this.userId$.pipe(filter(i => !!i))
]).pipe(
debounceTime(10),
switchMap(...)
);
ngOnInit() {
this.data$.subscribe(...);
}