繁体   English   中英

TypeScript:按顺序发送多个HTTP请求Angular2

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM