订阅可观察后的未定义string []

时间:2019-07-03 14:38:26

标签: angular rxjs

以下代码给出了运行时错误,因为top5Ids未定义。当我正确订阅可观察对象并从订户top5Ids方法内部设置next变量时,我真的不太理解为什么未定义此变量。

cryptoService类只是返回http.get()函数的结果,这是可以观察到的。

export class HomeComponent implements OnInit {

  cryptoDetails: CryptoDetail[];
  top5Ids: string[];

  constructor(private cryptoService: CryptoService) { }

  ngOnInit() {
    this.cryptoDetails = new Array();

    this.getTop5Crypto();
    this.getCryptoData(this.top5Ids);

    const source = interval(5000).subscribe(val => this.getCryptoData(this.top5Ids))

  }

  getCryptoData(ids: string[]){
    this.cryptoDetails = [];
    console.log("get crypto")
    for(let id of ids){
      this.cryptoService.getCryptoInfo(id).subscribe(res => {
        let data = res.data;
        let cryptoDetail = new CryptoDetail(data.id, data.rateUsd, data.symbol);
        this.cryptoDetails.push(cryptoDetail);

      })
    }

    this.cryptoDetails.sort();
  }

  getTop5Crypto() : void {

    let top5CryptoIds : string[] = [];
    this.cryptoService.getCryptoMarkets().pipe(take(1)).subscribe(res => {
      let data = res.data;
      for(let i = 0; i < 6; i++) {
        top5CryptoIds.push(data[i].baseId)
      }
      this.top5Ids = top5CryptoIds;
    });
  }

}

1 个答案:

答案 0 :(得分:1)

在Angular中,最好完全包含函数式反应式编程。

您可以按以下方式重写代码:

export class HomeComponent implements OnInit {

  cryptoDetails: CryptoDetail[];
  top5Ids$: Observable<string[]>;

  constructor(private cryptoService: CryptoService) { }

  ngOnInit() {
    this.top5Ids$ = this.getTop5Crypto();

    timer(0, 5000).pipe(
      switchMap(() => this.top5Ids$),
      switchMap((top5Ids) => this.getCryptoData(top5Ids))
    ).subscribe((cryptoDetails) => {
      this.cryptoDetails = cryptoDetails;
    })

  }


  getCryptoData(ids: string[]): Observable<CryptoDetail[]> {
    return forkJoin(ids.map(id => this.cryptoService.getCryptoInfo(id)))
            .pipe(
              map(responses => responses.map(r => new CryptoDetail(r.data.id, r.data.rateUsd, r.data.symbol)).sort())
            );
  }

  getTop5Crypto() : Observable<string[]> {
    return this.cryptoService.getCryptoMarkets().pipe(
      take(1),
      map((res: any) => res.data.filter((d, i) => i < 5).map(d => d.baseId)),
    );
  }
}

功能反应式编程的思想是,我们编写对DOM事件和Http响应之类的东西做出反应的代码,然后通过一系列(理想情况下是纯函数)将转换应用于与这些事件相关的数据。

我们尝试避免在管道结束时创建手动订阅(有时甚至在使用Angular异步管道时也是如此)。这样,我们得到了一个很好的可预测的异步事件管道,并避免了诸如竞争条件之类的问题。

警告是要执行这些操作,您必须对RxJS有深刻的了解。

相关问题