如何从Angular 4中的循环中等待每个HttpClient服务调用的响应

时间:2018-08-29 06:16:16

标签: angular typescript angular-httpclient angular4-httpclient

我遇到一种情况,我需要运行一个循环并获取各个项目的 说明 。然后,除了条目ID和其他信息之外,我还必须在数据表中包含获取的 说明

addDescription(){
this.arrayOfItems.forEach(element => {

   // CALL a function which will make a service call
   this.fetchDescription(element);

   //CODE TO DECLARE AN INTERFACE TO ASSIGN RESPECTIVE VALUES. eg.

   // ITEM_ID : element.id,
   // ITEM_DEF : this.fetchedDescription.join("\n")
}

功能主体:

fetchDescription(elementToFetchDesc){

 //Declaring HTTPPARAMS in PassingParams variable

 this.componentService.getDesc(PassingParams)
         .subscribe((response: HttpResponse<any>) => {
                if(response.status ==200){
                    this.fetchedDescription = reponse.body.output.slice(6,-1);
                }
                //Code if response status is NOT 200
}

componentService服务中:

construcutor(private httpConn: HttpClient){}

getDesc(Params){
    // Declare URL
    return this.httpConn.get(URL, {params: Params, observe: 'response'});
}

问题

由于它正在循环中运行,并且订阅是一个异步调用,因此,在forEach中运行循环之后,它就出来了。结果, 说明 没有分配给界面中的变量(ITEM_DEF)。

为解决此问题,我对使用promise进行了一些更改。 在服务中,我添加了:

 import 'rxjs/add/operator/toPromise';

并将服务方法更新为:

 return this.httpConn.get(URL, {params: Params, observe: 'response'})
                     .toPromise();    // converted observable into promise

还更改了组件: 在fetchDescription函数内部:

.subscribe替换为.then

但是问题仍然存在。请让我知道我在执行该逻辑时做错了什么。

3 个答案:

答案 0 :(得分:1)

解决方案是将可观察的转换为承诺,但不使用!!

示例:

这是您发送请求的服务功能:

myRequest(num) {
   return this.http.get('http://someUrl.com/' + num).toPromise(); 
}

这是在组件类中发送所有请求的功能:

 async sendAll() {
    let response = [];
    for(let i = 0; i < 5; i++) {
        response[i] = await this.myService.myRequest();
    }
  // Got all the results!
 }

答案 1 :(得分:0)

解决方案:

功能主体:

fetchDescription(elementToFetchDesc):  Observable<string> {

  //Declaring HTTPPARAMS in PassingParams variable

  return this.componentService.getDesc(PassingParams)
      .map((response: HttpResponse<any>) => {
          if(response.status ==200){
             return reponse.body.output.slice(6,-1);
          }
       });
     }
  }

致电:

this.fetchDescription(element).subscribe((description: string) => {
   ITEM_ID : element.id,
   ITEM_DEF : description
});

答案 2 :(得分:0)

为此,您应该使用 rxjs

checkStatus(url: string, id: string): Observable<string> {
const trigger$ = new Subject<string>();
const time = Date.now();

return trigger$.asObservable().startWith(url).concatMap((u) => {
  return this.ping(u).map(() => {
    trigger$.complete();

    return id;
  }).catch((err) => {
      trigger$.next(u);

    return Observable.empty<any>();
  });
});
}


protected ping(url: string): Observable<any> {
return this.http.get(url)
  .catch(err => Observable.throw(err));
}

concatMap 操作符仅在第一个可观察到的情况下(即,第一个API调用的响应可用)才触发下一个可观察到的事件。每当您在 trigger $ 主题上调用方法complete()时,它都会完成Observable和API的调用。您可能必须更改调用complete()的逻辑。