2

I need to send multiple HTTP PUT request to server sequentially (after the next request is only started after completing the previous request, the number of request is not fixed). If I use the below source code, all request will be sent

 `listURL.forEach(url => {
    const req = new HttpRequest('PUT', url, formData, { reportProgress: true});
    httpClient.request(req).subscribe(event=>{});
  });`

Is there anyway to execute the requests sequentially?

Waveter
  • 890
  • 10
  • 22

3 Answers3

5

You could use async/await with Promise to stream line this. Convert the observable to a promise using toPromise()

async doSomethingAsync() {
    for(let url of listURL) {
        const req = new HttpRequest('PUT', url, formData, { reportProgress: true});
        const result = await httpClient.request<ModelHere>(req).toPromise();
        // do something with result
    }
}

For more on async/await see also this excellent answer and scroll to the heading ES2017+: Promises with async/await.

Igor
  • 60,821
  • 10
  • 100
  • 175
  • I still have an issue with your answer, could you put it as a function that returns the last promise ? Written like this, it can't be re-used easily and need to be copy-pasted. ( I also have removed my previous comments as to not pollute your answer) –  Dec 06 '18 at 15:26
  • @trichetriche - The op is not very clear on if they want to use the result of each call in the next successive call which is why I originally wrote it like this so they could easily see that they can do something with the result. The `doSomethingAsync` returns a promise though (although it is not currently defined in the method signature as the return type). Maybe I am not understanding what you are asking though? – Igor Dec 06 '18 at 15:31
  • Put simply, I'm asking for a return statement :) –  Dec 06 '18 at 19:31
3

use reduce and switchMap :

['url 1', 'url 2'].reduce((acc, curr) => acc.pipe(
  mergeMap(_ => this.mockHttpCall(curr)),
  tap(value => console.log(value)),
), of(undefined)).subscribe(_ => console.log('done !'));

Stackblitz

  • Have the decency to comment when you downvote please, this solution works as expected. –  Dec 06 '18 at 15:15
1

If you are not familiar with rxjs, perhaps you can try the following?

let requests = listURL.map(url => new HttpRequest('PUT', url, formData, { reportProgress: true});

function do_seq(i) {
  httpClient.request(requests[i]).subscribe(event => {
   if (i < requests.length - 1) do_seq(i + 1);
  });
 }

do_seq(0);
ABOS
  • 3,723
  • 3
  • 17
  • 23