在http调用中获取值后如何返回函数?

时间:2019-09-01 08:13:44

标签: angular typescript asynchronous

我有这样的东西

getFieldsRemote(){

  let fields: FormfieldBase<any>[] = [];
   this.http.get('http://localhost:8080/api/getFields').subscribe(
    data =>{
       // code to push objects from data to fields variable declared above
           }

    }

  )
    return fields;
}

现在我面临的问题是,每当我从其他组件中调用此getFieldsRemote()方法时,我都会得到一个空白数组。  我知道发生这种情况是因为Subscribe方法是异步的,因此它在后台运行,并且在执行内部Subscribe的代码段之前,控件会到达return语句。但是,我需要此函数以某种方式在subscribe方法完成后返回数据。在组件端订阅数据不是一种选择。请告诉我这里的解决方案。

4 个答案:

答案 0 :(得分:2)

如果您确实要避免从组件中进行订阅,则可以将方法标记为async并等待http调用的响应。

async getFieldsRemoteAsync(){
  let fields = await this.http.get('http://localhost:8080/api/getFields').toPromise();
  return fields;
}

请注意,如果执行此操作,则还需要将Consumer方法标记为async,并且需要等待调用:

await getFieldsRemoteAsync();

答案 1 :(得分:0)

问题

如果订阅不是一种选择,而您想以可观察的方式进行订阅,那么此问题将无法解决。您需要订阅组件才能获取数据,但是最好在模板中使用async管道。这样,清理组件时,Angular会清理订阅。

解决方案

getFieldsRemote方法应通过以下方式返回Observable<FormfieldBase<any>>[]

import { Observable } from 'rxjs';

getFieldsRemote(): Observable<FormfieldBase<any>>[] {
   return this.http.get('http://localhost:8080/api/getFields');
}

此外,请尝试避免键入any并编写一个接口。然后在组件中,将getFieldsRemote()的结果分配给属性fields

@Component({
  ...
})
export class ExampleComponent implements OnInit {
  fields: Observable<FormfieldBase<any>>;

  constructor(private service: ExampleService) {}

  ngOnInit(): void {
    this.fields = this.service.getFieldsRemote();
  }
}

然后在您的模板中执行

<div *ngFor="let field of fields">
  <!-- Do something with your field -->
</div>

其他信息

如果问题是您的getFieldsRemote方法将由多个组件调用,并且您希望共享结果(不进行多次http调用),请查看share或{{1} } rxjs运算符。

例如:

shareReplay

但是您可能需要详细说明为什么“在组件端订阅数据不是一种选择。” ,因为这是一种明确的代码味道。

答案 2 :(得分:0)

您必须在组件内部订阅方法:

如果apiservice具有如下方法:

public getCustomer(customer: Customer){
    return this.httpClient.get(`${this.apiURL}/customers/`,customer);
}

像这样在组件内部使用它:

this.apiService.getCustomer(customer).subscribe((res)=>{
      console.log("get a customer", res);
});

注意:apiservice中的createCustomer返回一个可观察的

答案 3 :(得分:0)

如果您不想担心订阅,可以简单地变成一个承诺并使用async / await

async getFieldsRemote(){

  let fields: FormfieldBase<any>[] = [];
  const data = await this.http.get('http://localhost:8080/api/getFields').toPromise()
  // do what you want with the data
  return fields
}