在非数组类型上可观察

Observable over a non-array type

我创建了 3 个 Angular2 服务,它们从不同的 http 端点检索类别、位置和项目。我现在想创建一个新服务,从这些服务中检索数据并从所有检索到的数据中创建一个新的 DataSet,但我无法从不可迭代的 DataSet 对象中创建一个 Observable。

有没有更好的方法将数据合并到一个结构中,就像使用 Observables 一样?

export class DataSet {
  items: Item[];
  locations: Location[];
  categories: Category[];
}

@Injectable()
export class DataService {

_data : DataSet;

constructor(
    private _http: Http, 
    private _categoryService: CategoryService, 
    private _locationService: LocationService,
    private _itemService: ItemService) { }

getDataSet(): DataSet {
    this._data = new DataSet();

    this._categoryService.getCategories().subscribe(cats => {
        this._data.categories = cats;
    });

    this._locationService.getLocations().subscribe(locs => {
        this._data.locations = locs;
    });

    this._itemService.getItems(null).subscribe(items => {
        this._data.items = items;
    });

    // ERROR can't create observable from non array type dataset
    return Observable.from(this._data);
    }
}

是的,您需要使用 Observable.of,如

return Observable.of(this._data);

您可能需要使用

显式添加函数导入
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/of';

更新:

我对我的回答不满意,正如评论中指出的那样,它没有解决根本问题。所以我添加了一个解决方案

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

export class DataService {

  constructor(
    private http: Http,
    private categoryService: { getCategories(): Observable<{ categoryName: string }[]> },
    private locationService: { getLocations(): Observable<{ locationName: string }[]> },
    private itemService: { getItems(options): Observable<{ itemName: string }[]> }) { }

  getDataSet() {
    return Observable
      .forkJoin(
        this.categoryService.getCategories(),
        this.locationService.getLocations(),
        this.itemService.getItems(undefined)
      )
      .map(([categories, locations, items]) => ({
        categories,
        locations,
        items
      }));
  }
}

Observable.forkJoin 具有您正在寻找的语义,因为它通过将输入 Observable 排序到结果数组中来保留不同输入 Observable 之间的区别。

请注意,这也会清理我们的代码,因为不再有可变 class 字段。

一些想法:

我觉得有趣的是我不得不使用Observable.forkJoin(可能有更简单的方法,如果有请告诉我!)这不是一个很容易发现的功能,而且恰好没有ForkJoinObservable.d.ts.

中的文档

这让我感到困扰的原因是,这个问题描述了使用 Observable 作为 singular Web 请求的接口时的基本场景。如果我们相信 Observable 是这个用例的正确抽象,它应该是显而易见和直观的。

一旦我们谈论诸如预输入之类的东西,它们会随着时间的推移 return 在 0 和一些任意 n 值之间进行异步查询,那么是的,Observable 注入的 Web 请求似乎变得有价值。

唯一的问题是,typeahead 场景是 RxJS + Angular 的典型代表,无论如何涉及 flatMapping 结果。整个抽象被提升到 RxJS 已经适用、相关和优雅的水平,因为领域是流的领域。