Connecting http calls in angular 2 in a for loop

I have some code that looks like

//service.ts

addProduct(productId) {
   this.http.post('someUrl', ReqData).map(json).subscribe(doStuff);
}

//component.ts

addAllproducts(productsIds) {
   productIds.forEach(productId => service.addProduct(productId);
}

      

I want you to be able to wait for each call to complete before calling the next productId without using window.setTimeout

..

+3


source to share


3 answers


First, return the observable from your service method:

addProduct(productId) {
   return this.http.post('someUrl', ReqData).map(json).subscribe(doStuff);
}

      



And use a recursive function and call it in the callback subscribe

for each of the elements in your array:

let loop = (id: number) => {
  service.addProduct(id)
    .subscribe((result) => {
      // This logic can be modified to any way you want if you don't want to mutate the `producIds` array
      if (productIds.length) {
        loop(productIds.shift())
      }
    })
}

loop(productIds.shift())

      

+1


source


How about some recursive calls with . expand () ?

First, create a recursive function and map the data for recursive use:

const recursiveAddProduct = (currentProductId, index, arr)=>{
    return service.addProduct(currentProductId)
        .map((response)=>{
            return {
                data:response,
                index: index+1,
                arr:arr
            }
        })
};

      

Now call it recursively into your component:

//productIds is an array of Ids    
//start of using the first index of item, where index = 0

let reduced = recursiveAddProduct(productIds[0],0,productIds)
    .expand((res)=>{
        return res.index>res.arr.length-1 ? Observable.empty(): recursiveAddProduct(productIds[res.index],res.index,productIds)
    });

reduced.subscribe(x=>console.log(x));

      

This is where JSBin works



The advantage of using the operator .expand

:

  • You are still using Observables and can chain whatever operators you want.
  • You are calling one http after another, which is your requirement.
  • You don't need to worry about error handling, they are all tied to the same thread. Just call .catch

    your watchers.
  • You can do anything according to your recursion method (data manipulation, etc.).
  • You can set a condition when the recursion call needs to end.
  • One layer code (almost).

Edit

You can use the operator .take()

to terminate your recursion if you don't like the built-in triplet like:

let reduced = recursiveAddProduct(productIds[0],0,productIds)
    .expand(res=>recursiveAddProduct(productIds[res.index],res.index,productIds))
    .take(productIds.length)

      

JSBin work

+6


source


You can use Observable.merge (). Try something like this

addProduct(productId):Observable<Response> {
   return this.http.post('someUrl', productId);
}

addAllproducts(productsIds) {
   let productedsObservable:Observable<Response>[]=[];
   for(let productID in productsIds){
    this.productedsObservable.push(this.addProduct(productID));
   }
   return Observable.merge(productedsObservable)
}

      

You need to subscribe to the requested function to fulfill the http request. You can read more about combination operators (like merge) here

0


source







All Articles