I'm using ngrx in an Angular project. In this example I have an array of requests. I want to dispatch an action after each request but also after all are done.
So far I have something looking like this:
Observable.forkJoin(requests).pipe(
map(() => new actions.requestsSuccessful()),
catchError(() => of(new actions.requestsFailed()))
);
where requests is an array of Observables.
The code above works fine, when all requests are done, my requestsSuccessful() action is correctly dispatched.
However, I'm implementing a progressbar, which I want to update after each request has been made, but I also want to keep the dispatch of the action where all requests have been made.
I can't figure out how to dispatch an action after each request while keeping the action when everything is done.
Any ideas?
forkJoin emits only when all Observables complete so it's not useful here. Instead, you can use concatAll and concat.
This is model example simulating what you want if I understand you correctly.
const makeRequest = (v) => of(v)
.pipe(
delay(1000), // Simulate delay
map(response => ({ action: 'WHATEVER', response })), // Map response into action
);
const requests = [makeRequest(1), makeRequest(2), makeRequest(3)];
from(requests)
.pipe(
concatAll(), // Execute Observables in order one at the time
concat(of({ action: 'ALL_DONE' })), // Append this when all source Observables complete
)
.subscribe(console.log);
See live demo (open console): https://stackblitz.com/edit/rxjs6-demo-zyhuag?file=index.ts
This demo will print the following output:
{action: "WHATEVER", response: 1}
{action: "WHATEVER", response: 2}
{action: "WHATEVER", response: 3}
{action: "ALL_DONE"}
Btw, in future RxJS versions there will be endWith operator that you can use instead of concat that makes it more readable. https://github.com/ReactiveX/rxjs/pull/3679
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With