[英]TypeScript: Send multiple HTTP requests sequentially Angular2
我正在向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));
}
您可以使用称为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))
);
}
}
因此,在示例中,当我们获得家园世界时,我们正在角色Observable流中返回一个Observable。 这将在Observable中创建嵌套的Observable。 mergeMap运算符可通过订阅值并将其从内部Observable中拉出并将其传递回父流来帮助我们。
有关更多信息,您可以查看此博客: RxJS的角度多个HTTP请求
这个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));
}
我相信您正在寻找的是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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.