Chaining http calls in angular 2 in a for loop

前端 未结 3 739
挽巷
挽巷 2020-12-18 08:36

I have some code that looks like

//service.ts

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

//component.         


        
相关标签:
3条回答
  • 2020-12-18 08:55

    You can use the Observable.merge(). Try something like that

    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 for it the execute the http request. You can read more about combination operators (like merge) here

    0 讨论(0)
  • 2020-12-18 09:02

    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 subscribe callback for each of the items 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())
    
    0 讨论(0)
  • 2020-12-18 09:04

    How about some recursive calls using .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 in 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));
    

    Here is a working JSBin

    Benefit of using .expand operator:

    1. You are still using Observables and can chain whatever operators you want to.
    2. You are calling one http after another, which is your requirement.
    3. You don't need to worry about error handling, they are all chained to a single stream. Just call a .catch to your observables.
    4. You can do anything to your recursion method (data manipulation,etc)
    5. You can set the condition when to terminate the recursion call.
    6. One-liner (almost) code.

    Edit

    You can use .take() operator to terminate your recursion, if you don't like the inline ternary, like this:

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

    Working JSBin

    0 讨论(0)
提交回复
热议问题