4

I have following code in Angular 8:

fetchMedia() {
    this.mediaDetails.forEach(entry => {
        this.fetchSingleMedia(entry); // NEED TO MAKE THIS SEQUENTIAL
    }
  });
}

fetchSingleMedia(entry) {

  this.mediaService.getMedia(entry).subscribe(
    (data) => {
       // MY LOGIC HERE
    },
    error => {}
  );
}

The fetchSingleMedia method is used by other parts of the code as well. I want to keep the Logic in fetchSingleMedia itself

Now, if I have to sequentially make multiple requests to fetchSingleMedia method, how do I need to modify the fetchSingleMedia method and way of calling it? maybe using async/await/promise or rxjs?

Edit:

With concat, second request is sent before first's response is received. I want second request to go after first request's response is received

7
  • 1
    What do you mean by making it sequential? Do you mean synchronous? Commented Mar 3, 2020 at 6:51
  • Reactive programming ends with subscribe...don’t subscribe in fetchSingleMedia and use something like forkJoin in fetchMedia. Ugh, please don’t just use promises just because you don’t know RxJS fully yet, this leads to ugly code, mix and matching promises and observables. Commented Mar 3, 2020 at 6:53
  • @Shravan I mean one after another in a loop Commented Mar 3, 2020 at 6:58
  • @user5155835 what do you want to happen if one fetch fails? Why one after another (if it’s to protect the back end would a delay between requests suffice?)? Commented Mar 3, 2020 at 7:21
  • @AndrewAllen even if first fails, second request should be made. Just that, second request should be made after the first request is finished Commented Mar 3, 2020 at 10:13

1 Answer 1

5

Use concat to sequentially run an array of observables.

From the docs:

Subscribe to observables in order as previous completes

Build your array of observables first, and then run them sequentially in concat.

fetchMedia() {
  const observables = this.mediaDetails.map(entry => {
    return this.fetchSingleMedia(entry);
  });

  concat(...observables).subscribe(singleMedia => {
    console.log(singleMedia);
  },
  error => {
  });
}

fetchSingleMedia(entry): Observable<any> {
  return this.mediaService.getMedia(entry).pipe(
    catchError(() => of('Error')), // TODO: return simple error result here, 
    tap(mediaEntry => console.log(mediaEntry)) // TODO: any processing here
  );
}

Note that you will need to handle errors on the individual observables if you want to ignore errors. I have shown a very simplistic way to do this.

DEMO: https://stackblitz.com/edit/angular-mhrxha

Sign up to request clarification or add additional context in comments.

18 Comments

There’s also materialise and dematerialise (advanced RxJS) for fine grained control and allowing rest of observables to pass through stream unimpeded by an error.
Even if first request fails, the second request will still be made, right?
@user5155835 You can set it up however you want to. Do you want all requests to run even if the first one fails?
Yes, all requests should run even if any of the request fails
That's what my example will do. In my stackblitz, I set up a concat from a sequence of integers. #2 throws an error, but you still see numbers 3+.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.