【问题标题】:How to return an observable from an array of observables如何从可观察对象数组中返回可观察对象
【发布时间】:2018-12-16 07:38:30
【问题描述】:

我开始使用 Angular 6 和 Firebase。我想使用 Hacker News API 来显示提要(事物)。

我想返回一个 Thing 类数组的 observable。首先,我需要一组提要 ID,因此我调用 Firebase 来获取这些 ID。然后我想获取我已经拥有的每个 ID 的提要,并将其作为提要数组的单个可观察对象返回。

我目前的代码是这样的:

getThings(limit: number): Observable<any> {
  return this.db.list('/v0/beststories', ref => ref.limitToFirst(limit).orderByKey())
    .valueChanges() // returns an Observable of IDs
    .pipe(
      flatMap(itemIds => {
        if (itemIds.length > 0) {
          let sources = itemIds.map(itemId => defer(() => {
            let pathOrRef = '/v0/item/' + itemId;
            return this.db.object(pathOrRef).valueChanges();
          }));
          // sources are the array of Observables
          return forkJoin(sources);
        } else {
          return Observable.create([]);
        }
      })
    );
}

我认为来自数组的 flatMapping 将是解决方案,但我得到了You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable

我尝试以与 RxJs Array of Observable to Array 类似的方式执行此操作,但我不知道我在哪里犯了错误。

在返回的 Observable 上调用 subscribe 后抛出错误:

this.hackerNewsService.getThings(20).subscribe(console.log);

我在下面的sn-p中重现了类似的情况:https://stackblitz.com/edit/angular-8qtokd?file=src%2Fapp%2Fapp.component.ts

【问题讨论】:

  • 我认为flatMap 像你在else 中所做的那样将一个可观察的作为回报。因此,您需要使用 of 或在 flatMap 内进行另一个 http 调用并返回 observable。
  • 哪里抛出的错误?甚至在这个flatMap 中吗?
  • @windmaomao 我不明白你所说的“flatMap 中的另一个调用”是什么意思。你能用一些sn-p来展示它吗?

标签: angular typescript firebase-realtime-database


【解决方案1】:

尝试使用switchMapcombineLatest。例如

import {combineLatest, Observable} from 'rxjs';
import {map, switchMap} from 'rxjs/operators';

function getThings(limit: number): Observable<any> {
    return this.db.list('/v0/beststories', ref => ref.limitToFirst(limit).orderByKey())
        .valueChanges() // returns an Observable of IDs
        .pipe(
            switchMap(itemIds => {
                if (itemIds.length > 0) {
                    let sources = itemIds.map(itemId => {
                        let pathOrRef = '/v0/item/' + itemId;
                        return this.db.object(pathOrRef).valueChanges();
                    });
                    // sources are the array of Observables
                    return combineLatest(sources);
                } else {
                    return Observable.create([]);
                }
            })
        );
}

【讨论】:

    猜你喜欢
    • 2018-04-11
    • 2019-02-18
    • 2017-07-12
    • 2019-09-09
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 2020-12-01
    • 1970-01-01
    相关资源
    最近更新 更多