将一组Observable转换为一个数组

时间:2018-02-13 13:55:09

标签: javascript angular rxjs

我正在使用forkJoin将多个可观察对象转换为一个可映射的对象,然后我将其映射为转换为我在组件中用于视图的视图模型。

我的模型如下:

export interface MyModel {
    itemOne: Observable<ItemOne[]>;
    itemTwo: Observable<ItemTwo[]>;
    itemThree: Observable<ItemThree[]>;
}

我的forkJoin看起来像是:

this._subscriptions.push(this.myService.getData()
    .flatMap(data => Observable.forkJoin(data
        .map(data => {
            let myModel: MyModel = {
                itemOne: this.myService.getSomeData(),
                itemTwo: this.myService.getSomeData(),
                itemThree: this.myService.getSomeData()
            };
            return Observable.forkJoin(Observable.from([myModel]));
}))).subscribe(details => {
    details.map(this.toMyModelViewModel.bind(this));
}));

现在,在我的toMyModelViewModel方法中,我想从这些Observable中选择每个值,并想知道如何实现这个目标?

toMyModelViewModel(value: MyModel): any {
    return {
        itemOne: value.itemOne,
        itemTwo: value.itemTwo,
        itemThree: value.itemThree
    };
}

我是否必须订阅每个值才能获得当前值,或者是否有另一种可能更好/更清洁的方法?最后,我希望有一个MyModel对象数组,这样我就不必担心在我的视图中使用data | async

由于

2 个答案:

答案 0 :(得分:1)

从代码的快速扫描中,您似乎有一个初始的api调用(this.myService.getData()),您将从中调用结果,但结果是基于组合几个api调用的结果({ {1}})。

我觉得您需要this.myService.getSomeData()界面没有Observables:

MyModel

... export interface MyModel { itemOne: ItemOne[]; itemTwo: ItemTwo[]; itemThree: ItemThree[]; } 是一种工厂方法:

toMyViewModel

...然后您使用switchMap / forkJoin,如下所示:

function toMyModelViewModel(itemOne: any, itemTwo: any, itemThree: any): MyModel {
    return {
        itemOne: itemOne as ItemOne[],
        itemTwo: itemTwo as ItemTwo[],
        itemThree: itemThree as ItemThree[]
    } as MyModel;
}

答案 1 :(得分:1)

您可以使用您喜欢的任何方法将可观察数组转换为数组的可观察数据 - 米勒在其答案中显示的方法将起作用。我个人喜欢combineLatest技巧(引用redent84对这个问题的回答:How do I create an observable of an array from an array of observables?)。

let arrayOfObservables: [Observable<E>] = ...
let wholeSequence: Observable<[E]> = Observable.combineLatest(arrayOfObservables) 

现在,对于你真正的问题:

  

我是否必须订阅每个值才能获得当前值,或者是否有另一种可能更好/更清洁的方法?最后,我想拥有一个MyModel对象数组,这样我就不用担心使用数据了在我看来是异步。

不幸的是,从Array<any>中获取Observable<Array<any>>的唯一方法是订阅该observable并将内部值保存到其他地方定义的数组,或者(如果您使用Angular作为你是),使用async管道。

你可以这样想:一旦Observable,一直是Observable。如果值包含在Observable中,则无法将其删除。与此行为最接近的可能是BehaviorSubject使用getValue方法,但它绝对不是Observables的选项。这是一件好事,因为它会阻止您尝试在程序中“同步”使用异步值。

我还觉得我应该提到async管道是一个非常有用的实用程序,应该首选手动订阅。在组件类中手动创建订阅时,您需要记住保存该订阅并在ngOnDestroy生命周期挂钩中清除它。 async管道非常棒,因为它可以为您完成所有这些清理工作。另外,您可以将其与safe navigation operator一起使用来处理未定义的值。

<ul>
  <li *ngFor="let obj of (possiblyUndefined$ | async)?.objects">
    {{ obj.title }}
  </li>
</ul>

如果您在组件类中编写了所有代码,那么代码将会更复杂

总结:

1)你可以使用Observable.combineLatest(arrayOfObservables)将你的observable数组压缩成一个可观察的数组。
2)你无法从一个可观察的数据中获得一个数组。您必须订阅该observable或使用async管道。