我正在向Web API发送请求,并根据第一次API返回的返回值再次向同一API发送请求。然后我试图将Web API组件映射到一个类,但map方法不等待第二次调用返回。请帮助我们在成功返回两个电话后如何映射?
以下是我的代码
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));
}
答案 0 :(得分:1)
您可以使用名为 MergeMap 的RxJs运算符(也称为 flatMap )来映射/迭代Observable值。
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))
);
}
}
因此,在我们获得homeworld的示例中,我们在我们的角色Observable流中返回一个Observable。这在Observable中创建了一个嵌套的Observable。 mergeMap运算符通过订阅并从内部Observable中提取值并将其传递回父流来帮助我们。
有关详情,您可以查看此博客:Angular Multiple HTTP Requests with RxJS
答案 1 :(得分:0)
这个flatMap运算符与forkJoin一起应该可以解决问题..
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));
}
答案 2 :(得分:0)
我相信您正在寻找的是expand方法。
以下是我自己的一个例子:
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);
}