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
..
source to share
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())
source to share
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
source to share
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
source to share