1

我创建了 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);
    }
}
4

1 回答 1

1

是的,您需要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 之间的区别。

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

只是一些想法:

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

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

一旦我们谈论诸如 typeahead 输入之类的东西,它执行异步查询,随着时间的推移返回 0 和一些任意 n 值之间,那么是的,Observable imbued Web Requests 似乎变得有价值。

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

于 2017-02-24T02:56:35.507 回答