【问题标题】:How do I return function after getting the value in http call?在http调用中获取值后如何返回函数?
【发布时间】:2019-09-01 08:13:44
【问题描述】:

我有这样的事情

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 语句。但是,当订阅方法完成时,我需要这个函数以某种方式返回数据。订阅组件端的数据不是一种选择。请告诉我这里的解决方案是什么。

【问题讨论】:

  • 订阅组件端的数据不是一种选择:太糟糕了,因为这正是解决方案。您的方法应该返回一个 Observable[]>,并且组件(或其视图,通过异步管道)应该订阅它。为什么要排除正确的做法?

标签: angular typescript asynchronous


【解决方案1】:

如果您真的想避免订阅组件,可以将方法标记为异步并等待来自 http 调用的响应。

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

请注意,如果您这样做,消费者方法也需要标记为异步并且需要等待调用:

await getFieldsRemoteAsync();

【讨论】:

  • 感谢您指出消费者方法也必须标记为异步。这真的很有帮助。
【解决方案2】:

如果你不想担心订阅,你可以简单地变成一个承诺并使用 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
}

【讨论】:

  • 这正是我想要的。我不能感谢你。这解决了我的问题。我也感谢您的及时回复。
【解决方案3】:

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

如果 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 返回一个 observable

【讨论】:

    【解决方案4】:

    问题

    如果订阅不是一个选项,并且您想以 Observable 方式进行,那么这个问题就无法解决。您需要在组件中订阅才能获取数据,但最好在模板中使用async 管道。这样,订阅就在组件被清理的时候被Angular清理掉了。

    解决方案

    getFieldsRemote 方法应该返回一个 Observable&lt;FormfieldBase&lt;any&gt;&gt;[] 这样做:

    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 调用),那么请查看 shareshareReplay rxjs 运算符。

    例如:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-12
      • 2011-11-13
      • 1970-01-01
      • 2017-11-05
      • 1970-01-01
      • 2015-12-03
      • 1970-01-01
      相关资源
      最近更新 更多