1
votes

I want to build a list of observables as a user interacts with the page. Each observable is individually subscribed, but I would like another function to be called after individual or multiple concurrent API calls are made.

I have each function pushing an observable to an array, and I have a forkJoin and subscription to the array in my ngOnInit, but this fires only once. How can I make a live subscription that will do a callback function once all current API calls return and continue to do so as the user continues to make API calls?

For example, the user clicks "Create Thing," then does nothing.

forkJoin(thingsInProgress).subscribe(() => doStuffWhenAllResolve())

...

createThing() {
    const = this.thingService.createThing().pipe(tap(() => doStuff()));
    thingsInProgress.push(createThing$);
    createThing$.subscribe();
}

deleteThing() {
    ...
}

updateThing() {
    ...
}

I want doStuff() to fire, then doStuffWhenAllResolve() to fire. Or, if user clicks "Create Thing", "Delete Thing", "Update Thing" all within milliseconds of each other, doStuff() (for example) is called once for each, and doStuffWhenAllResolve() is called once for all.

Then, if the user creates 10 more things really quickly, doStuffWhenAllResolve() is called once more after all overlapping API calls return.

What RXJS operator am I looking for here?

1

1 Answers

1
votes

I would make a BehaviorSubject where createThing(), deleteThing(), and updateThing() each emit and couple it with a debounceTime.

Something like this:

actionMade$ = new BehaviourSubject(new Date());

this.actionMade$.pipe(
  debounceTime(100), // Up to you to play with this 100, basically how long in ms does it have 
                     // to wait before accepting a new actionMade$
  switchMap(() => forkJoin(thingsInProgress)),
).subscribe(() => doStuffWhenAllResolve());

createThing() {
  ...
  this.actionMade$.next(new Date());
}

deleteThing() {
  ...
  this.actionMade$.next(new Date());
}

updateThing() {
  ...
  this.actionMade$.next(new Date());
}

ngOnDestroy() {
  this.actionMade$.complete();
}

==================================================== Be sure to unsubscribe from your subscriptions (using sub.unsubscribe or takeUntil) or else they can make a memory leak.