简体   繁体   English

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

[英]TypeScript: Send multiple HTTP requests sequentially Angular2

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. 我正在向Web API发送请求,并基于第一次API返回的返回值再次向同一API发送另一个请求。 Then I am trying to map the Web API components to a class, but map method doesn't wait for second call to return. 然后,我尝试将Web API组件映射到一个类,但是map方法不等待第二次调用返回。 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));

} }

You can use an RxJs operator called MergeMap also known as flatMap to map/iterate over the Observable values. 您可以使用称为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))
    );
  }
}

So in our example when we get the homeworld, we are getting back an Observable inside our character Observable stream. 因此,在示例中,当我们获得家园世界时,我们正在角色Observable流中返回一个Observable。 This creates a nested Observable in an Observable. 这将在Observable中创建嵌套的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. mergeMap运算符可通过订阅值并将其从内部Observable中拉出并将其传递回父流来帮助我们。

For more you can checkout this blog: Angular Multiple HTTP Requests with RxJS 有关更多信息,您可以查看此博客: RxJS的角度多个HTTP请求

This flatMap operator, in conjunction with forkJoin should do the trick.. 这个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));
}

I believe what you're looking for is the expand method. 我相信您正在寻找的是expand方法。

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);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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