Reputation: 1
I am sending a request to Web API and sending again another request to the same API based on the return value from first API return. Then I am trying to map the Web API components to a class, but map method doesn't wait for second call to return. Please help that how can i map after successful return of both calls?
Below is my code
getOrderDetail(orderId: string): Observable<OrderHeader> {
return this.svc.wCWebClientServiceGetOrderDetails({ _orderId: orderId })
.do(order => {
order.SalesLines.forEach(saleLine => {
if (saleLine.RelatedOrders !== undefined && saleLine.RelatedOrders.length > 0) {
saleLine.RelatedOrders.forEach(relatedOrder => {
this.svc.wCWebClientServiceGetOrderDetails({ _orderId: relatedOrder.TransId })
.subscribe(relOrder => {
//debugger;
relOrder.SalesLines.forEach(relLine => {
order.SalesLines.push(relLine);
});
})
});
}
})
})
//.do(order => console.log('Received order', order))
.map(order => this.transformOrder(order));
}
Upvotes: 0
Views: 1505
Reputation: 176
I believe what you're looking for is the expand method.
Here's an example of my own:
VA7B(params: VA7B, accountList: any, balanceSequenceList: string[], docNumber: string) {
const sequenceList = [...balanceSequenceList];
// Função que define o código do balanço financeiro para a conta atual
const setBalanceCode = () => {
params.balance.accountNumberRecalled = StringFormat.padLeft('', 7);
params.balance.demoAccountNumber = sequenceList[0];
sequenceList.shift();
};
const total = accountList.reduce((acc: any, curr: any) => acc + curr.length, 0);
// Função que realiza a requisição RESTFUL ao servidor.
const post = (account: string): Observable<VA7BResponse> => {
const payload: PayLoad<VA7B> = new PayLoad<VA7B>();
params.balance.document.number = docNumber;
payload.obj = params;
payload.obj.balance.accountData = account;
payload.url = 'url_VA7B';
payload.result = VA7BResponse;
payload.hasCripto = this.hasCripto;
payload.criptoFields = [{ balance: Object, document: Object, number: String }];
payload.decriptoFields = [];
return this.baseService.POST<VA7B>(payload);
};
setBalanceCode();
// O método 'expand' é responsável por chamar a função REST recursivamente, caso ainda hajam contas a ser importadas.
return post(accountList[0][0])
.expand((res: VA7BResponse) => {
params.balance.accountNumberRecalled = accountList[0][0].substr(-25, 7);
accountList[0].shift(); // Após ser importado, o primeiro item é removido da lista.
// Caso a primeira lista esteja vazia, remove a lista e passa para o próximo demonstrativo.
if (accountList[0].length === 0) {
accountList.shift();
setBalanceCode();
// Caso não hajam mais balanços, encerra o processo e retorna.
if (accountList.length === 0) {
return Observable.empty();
}
}
return post(accountList[0][0]);
}).take(total);
}
Upvotes: 0
Reputation: 2643
You can use an RxJs operator called MergeMap also known as flatMap to map/iterate over the Observable values.
import { Component } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { mergeMap } from 'rxjs/operators';
@Component({
selector: 'app-root',
templateUrl: 'app/app.component.html'
})
export class AppComponent {
homeworld: Observable<{}>;
constructor(private http: HttpClient) { }
ngOnInit() {
this.homeworld = this.http.get('/api/people/1').pipe(
mergeMap(character => this.http.get(character.homeworld))
);
}
}
So in our example when we get the homeworld, we are getting back an Observable inside our character Observable stream. This creates a nested Observable in an Observable. The mergeMap operator helps us by subscribing and pulling the value out of the inner Observable and passing it back to the parent stream.
For more you can checkout this blog: Angular Multiple HTTP Requests with RxJS
Upvotes: 1
Reputation: 3724
This flatMap operator, in conjunction with forkJoin should do the trick..
getOrderDetail(orderId: string): Observable<OrderHeader> {
return this.svc.wCWebClientServiceGetOrderDetails({ _orderId: orderId })
.flatMap(order => {
order.SalesLines.forEach(saleLine => {
let observables:Array<Observable<any>> = [];
if ( /* Your predicate */ ) {
saleLine.RelatedOrders.forEach(relatedOrder => {
observables.push(this.svc.wCWebClientServiceGetOrderDetails({ _orderId: relatedOrder.TransId }));
});
}
// Perform the calls to retrieve order details asynchronously
return Observable.forkJoin(observables).map((results:Array<any>) => {
results.forEach(relOrder => {
relOrder.SalesLines.forEach(relLine => {
order.SalesLines.push(relLine);
});
});
});
});
})
// Perform your final transformation on the results
.map(order => this.transformOrder(order));
}
Upvotes: 0