角度:等待异步数据加载的正确方法

时间:2018-12-12 23:30:39

标签: angular typescript

我必须进行多个API调用(http请求)才能获取所需的所有数据。

由于我必须进行2个独立的API调用,两个调用均应以检索数据完成,因此我尝试与之同步。

我在打字稿/角度方面有将近0的经验,并且无法通过Google找到解决方案。

以下是我正在进行的API调用(签名):

public supportedLanguages(observe?: 'body', reportProgress?: boolean): Observable<Array<string>>;
public getAllFilters(acceptLanguage?: string, observe?: 'body', reportProgress?: boolean): Observable<Array<Filter>>;

这是我当前用来填写Array<Type>的代码:

this.langService.supportedLanguages().subscribe(langs => setTimeout(() =>
  this.langs.push(...langs), 1000));
this.categorieService.getAllFilters('de').subscribe(categories => setTimeout(() => {
  this.categories.push(...categories), 1000));

我猜测这不是检索数据的正确方法,但是我还没有找到更好的方法(我对Typescript / angular非常陌生)。

等待加载所述数据的正确步骤是什么?

5 个答案:

答案 0 :(得分:3)

您可以使用

(我正在使用“ rxjs”:“ ^ 5.5.11”)。

  

forkJoin

import 'rxjs/add/observable/forkJoin';
import { Observable } from 'rxjs';
import { Subscription } from 'rxjs/Subscription';


/* Multiple Service calls are asynchronism. use forkJoin to group service calls */  
Observable.forkJoin(
  this.supportedLanguages();
  this.getAllFilters()
).subscribe(
    response =>{
      //response[0] is data returned by API supportedLanguages
      //response[1] is data returned by API getAllFilters
    }
    error => console.log("Error: ", error),
    () =>{
      //All the API calls are completed here. Put your code here
      //codes should be executed after the completion of all API calls
    }
)

答案 1 :(得分:1)

您可以尝试从rxjs进行forkJoin:

forkJoin(
    this.langService.supportedLanguages(),
    this.categorieService.getAllFilters('de'))
)
.subscribe([langs, categories]=>{
  ...
})

答案 2 :(得分:1)

您也可以只使用async,await和promises的组合。
首先,您必须将.toPromise()附加到服务方法中。然后在component.ts文件中添加以下方法...

private async fetchData() {
  return await Promise.all([
    this.langService.supportedLanguages();
    this.categoryService.getAllFilters();
  ]).then(res => {
    this.langs.push(res[0]);   //res[0] is data returned by API supportedLanguages
    this.categories.push(res[1]); //res[1] is data returned by API getAllFilters
    this.status = true; // Confirms that now you have all your data back
  }
}

this.fetchData()内致电ngOnInit()

然后,您可能会有一个状态变量,该变量已初始化为false,然后在返回所有数据后将其设置为true

答案 3 :(得分:0)

  

您可以在Rxjs 6中使用 ForkJoin

import {forkJoin} from 'rxjs';

// ...

forkJoin(
    this.langService.supportedLanguages(),
    this.categorieService.getAllFilters('de'))
).subscribe([langs, categories] => {
  // ...
})
  

或者,您可以将2个API调用放在 Promise 中:

function recoverData() {
    return new Promise((resolve, reject) => {
        this.langService.supportedLanguages().subscribe(langs => this.langs.push(...langs), 1000);
        this.categorieService.getAllFilters('de').subscribe(categories => this.categories.push(...categories), 1000);

        resolve();
    });
}

然后像这样使用它:

recoverData().then(() => {
    // Some code
});

答案 4 :(得分:0)

如果您希望同时调用API并同时返回,则可以使用 rxjs 中的 ForkJoin ,有关documentation

forkJoin(
    this.langService.supportedLanguages(),
    this.categorieService.getAllFilters('de'))
).subscribe(x => 
console.log(x[0]); //result from api call 1
console.log(x[1]); //result from api call 2
 )

但是如果要调用第一个api,则在第一个api完成后,您要调用第二个api。您可以使用 concatMap ,查看有关documentation here的信息,可能在第二个api需要第一个

参数时使用的concat映射
this.langService.supportedLanguages().pipe( 
 concatMap(resultFromApi1 => this.categorieService.getAllFilters('de'))
).subscribe(x => console.log(x)) //x = result from api 2;
  

我在打字稿/角度方面有将近0的经验,找不到   通过Google解决方案。

您必须尝试不同的方式,不仅导致角度变角。如“ rxjs”等。您需要知道使用的是什么库js。并仔细对待版本,确实会造成一些棱角分明-关于版本,确实令人困惑,并且由于结构写法有些不同而有所不同