Chaining http calls in angular 2 in a for loop

你离开我真会死。 提交于 2019-12-18 05:13:09

问题


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);
}

What I want is to be able to wait for each call to finish before calling for the next productId, without using window.setTimeout ..


回答1:


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())



回答2:


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




回答3:


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



来源:https://stackoverflow.com/questions/45035184/chaining-http-calls-in-angular-2-in-a-for-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!