从Angular服务和组件中的observable返回和接收转换数据的正确方法是什么?

时间:2018-04-29 23:32:57

标签: angular asynchronous service async-await observable

我有一个配置为Observable的基本服务。

我将服务注入到一个组件中,该组件订阅了服务的以下方法,该方法触发了对数据的http请求:

listApi(params:any) Observable<any[]> {
...
return this.http.get(params.url, ampOptions)
                    .map(data => this.listExtract(response, params))
                    .catch(this.handleError);
}

我需要循环并转换响应,以确保在返回到我的组件之前完成

为实现这一目标,我尝试使用async函数awaitPromise.all

async listExtract(response:any, params:any) {
  let newArray:any = [];
  await Promise.all(response.map((item, index) => {
      if(item.id === params.id) {
       // make changes to specific item if it's id is a match
       item.label = 'selected';
      }
      newArray.push(item);
  });
  // i am assuming the above promise.all is guaranteed
  // to complete before returning the new array, correct??
  return newArray;
}

在我的组件中,我订阅了我服务中的listApi方法:

this.listService.listApi(params)
      .subscribe(
        response => this.listServiceResponse(response),
        error => this.serviceError = <any>error);

响应出现以正确显示,但因为我使用了转换数据的承诺,所以它包含在标题为ZoneAwarePromise的对象中:

listServiceResponse(response) {
   // because i used an async function in the service,
   // Angular returns the response wrapped in an
   // object titled ZoneAwarePromise
   console.log('response:',response);
}

如果上面使用 async 函数的方法对于首先转换数据有效,我该如何正确接收此响应?或者我应该以完全不同的方式解决这个问题?

我可以从ZoneAwarePromise对象中提取响应,但这似乎不可靠,仅作为示例,以下可以正常工作,但这不可能是正确的方法:

listServiceResponse(response) {
       // attempt to use a .then to extract the data
       response.then((extractedArray) => {
         console.log('response:',extractedArray);
       }
}

是否有其他方法可能使用更复杂的映射方法?

ANY 非常感谢。

1 个答案:

答案 0 :(得分:0)

您应该可以直接使用observable。在您的服务返回内容之前,订阅方法不会被触发,因此您应该能够在调用之前执行所需的所有处理。我认为您可以简化listExtract,以便它只处理将响应转换为您的数组的操作,而不必担心任何异步业务。

listExtract(response:any, params:any): any[] {
  let results: any[] = response.results;
  return results.map(item => {
    if (item.id == params.id)
      item.label = 'selected';
    return item;
  });
}

然后您的listApi方法可以保持大致相同,但实际上您应该使用您拥有的data参数,这将是http响应。

listApi(params:any) Observable<any[]> {
  return this.http.get(params.url, ampOptions)
                    .map(data => this.listExtract(data, params))
                    .catch(this.handleError);
}

然后,您在组件中使用此listApi服务调用应该足够简单:

this.listService.listApi(params)
      .subscribe(array_of_things = this.workWithMyList(array_of_things));

此处的observable可以消除手动处理数据的异步性质的任何需要。当您的订阅被触发时,数据已经存在。