Как дождаться ответа http перед выполнением бэкэнд-вызова в Angular - PullRequest
0 голосов
/ 06 мая 2020

Я новичок в angular, я пытаюсь сделать HTTP-запрос на получение и, основываясь на его ответе, мне нужно сделать внутренний вызов.

Здесь я пытаюсь связать 2 вызова asyn c, не уверен, что это выполнимый / правильный подход в Angular (с использованием версии Angular 7).

Постановка проблемы : Второй (Backend) вызов aysn c выполняется до получения ответа от первого (http) asyn c вызова.

Я пробовал реализовать с помощью async / await (не понимаю, что это правильно , но все же попробовал) и вызов бэкэнд-вызова в подписке на 1-й http-вызов. Оба подхода не сработали. Пожалуйста, дайте мне знать, что здесь происходит не так и есть ли лучший способ связать 2 асинхронных c вызова.

Ниже приведен фрагмент кода (упрощенная версия)

export class BasicService{ 
let httpUrl:string=null;
  constructor(protected http: HttpClient, protected backendSvc: BackendService) {
      httpUrl='/someUrl';
  }

  getComponentData(route: ActivatedRoute): Observable<ComponentData> {
    let callName:string;
    let inputPayload:string;
    let routeID=route.snapshot.url[0].path;

if (routeID.Equals('Test')) {
  callName='TestCall';
}
else if (routeID.Equals('Execute')) {
  callName='ExecuteCall';
}

//Failure#1: Get http response back and then call backendSvc, inputPayload remains empty
//want to wait for _waitCreateInputPayload to finish execution before calling backendSvc
inputPayload = this._waitCreateInputPayload(httpUrl,callName);  
//backendSvc returns an observable
return this.backendSvc.GetData(callName, inputPayload, null, this.FormFactorType);

//Failure#2: This approach also doesn't work.
this._createInputPayload(httpUrl,callName).subscribe(tempVal=>{
    if(tempVal!=undefined){
        return this.backendSvc.GetData(callName, tempVal, null, this.FormFactorType);
    }else{
        return null;
    }
});
  }

      private async _waitCreateInputPayload(httpUrl: string, callName:string){
        return await this.http.get(httpUrl, { responseType: 'text' }).subscribe(tempVal=>{
          console.log('in _createInputPayload');
          return tempVal;
        });
      } 


private _createInputPayload(httpUrl: string, callName:string): string{
    return this.http.get(httpUrl, { responseType: 'text' });
  } 
}

код компонента выглядит так:

    export class ChildTemplateComponent implements OnInit {

  constructor(protected basicSvc: BasicService, protected route: ActivatedRoute) {}

  ngOnInit() {
    this.formFactorSvc = this.route.snapshot.data['formFactor'];
    this.formFactorSvc.getDesignConfig(this.route);
  }

  ngInit() {
    this.basicSvc.getComponentData(this.route).subscribe((x) => {
      this.populateData(x);
    });
  }

  populateData(data: ComponentData){
  //populate the View
  }
}

Спасибо,

RDV

Ответы [ 2 ]

1 голос
/ 06 мая 2020

с помощью Rx Js вы можете передать по конвейеру возврат от _createInputPayload, в конвейере вы можете вставить результат из _createInputPayload в переменную-член, тогда mergeMap вызовет GetData. Когда вы подписываетесь на getComponentData из компонента, подписка будет на GetData, поскольку это последняя карта mergeMap.

return this._createInputPayload(this.httpUrl, callName).pipe( tap((input) => inputPayload = input), mergeMap(() => this.backendSvc.GetData(callName, inputPayload, null, this.FormFactorType)));

0 голосов
/ 06 мая 2020

_createInputPayload должен возвращать Obseravble, а не строку, поскольку http.get возвращает Observable. Как только вы измените это, вы можете подписаться на него, и тогда вы получите HTTP-ответ перед выполнением внутреннего вызова.

...