How to make multiple http requests at angular?

Asked

Viewed 416 times

1

I need to make an http request for each element of my product array.

I tried to do with for() but sometimes it doesn’t work, my browser stops working and it costs to close (I thought it could be because of the number of requests fired, but currently I’m testing with only two elements in the array and the browser keeps crashing).

I tried that way:

for(let i=0;i<this.produtosConfirmadosAnuncio.length;i++){
    this.marketplaceService.anunciar(this.produtosConfirmadosAnuncio[i])

.pipe(
        take(1)
    )
    .subscribe((res) => {

        this.submited = false;

        for (let c = 0; c < this.produtosConfirmadosAnuncio.length; c++) {
            if (this.produtosConfirmadosAnuncio[c].id == this.produtosConfirmadosAnuncio[i].id) {
                this.produtosConfirmadosAnuncio.splice(c, 1)
            }
            c--;
        } //Remove the element when requisition return success


        this.valorAtualProgress += this.quantidadeSomarProgress; //sum progress bar


        if (this.valorAtualProgress == 100) { //close the progress bar when value is 100
            this.toastrService.showToast(true, "Pronto!", res.mensagem);
        }

    }, (err) => {
        this.loadingprogress = false
        if (err.status == 401) {
            this.authService.Logout();
        }
    })
}

Is there any other way I might be making multiple http requests?

2 answers

1

I believe that the cause of the problem is because your method returns an observable, ie the processing is asynchronous. But its for will proceed to the next interaction even if the observable return has not occurred. In a loop of 1000 interactions for example javascript will trigger 1000 requests and register their respective observable. In this case I suggest you treat your problem in 2 possible ways:

  1. Submit a single request containing an object with the array of items you need to submit. In this case instead of looping multiple requests, you do the for-only to create an object with the items and submit this object in your request. This implies changing your API to meet this change.
  2. Create a method that can control this queue of items that need to be sent, so that a kind of request buffer is made. Your method can receive the list of items and return an observable to signal when the operation is completed.
  • There is a Pattern called Publisher Consumer that you can use as a reference to your problem.

1


The solution will depend a lot on the context of your problem and the outcome you expect.

Answering your headline question: what you want will probably involve the operator mergeMap. With it, your sending can become more declarative:

import { from } from 'rxjs';
import { mergeMap } from 'rxjs/operators';

...

from(this.produtosConfirmadosAnuncio).pipe(
  mergeMap(produto => this.marketplaceService.anunciar(produto))
).subscribe(
  resp => {
    this.valorAtualProgress += this.quantidadeSomarProgress;
  },
  err => {
    this.loadingprogress = false;
    if (err.status == 401) {
      this.authService.Logout();
    }
  },
  () => {
    this.toastrService.showToast(true, 'Pronto!');
  }
);
  • mergemap would have you waiting for the current request to subscribe to the next?

  • 1

    @Renatoveronese O mergeMap has a parameter called Concurrent that controls how many subscribers internal exist at the same time. The default value is Number.POSITIVE_INFINITY, that is, by default "infinite" requests will be made simultaneously. You can limit the number of simultaneous requests by changing this parameter.

  • I’ll test and return here

  • By the tests I did apparently worked very well, thank you

Browser other questions tagged

You are not signed in. Login or sign up in order to post.