将动态数组的动态数组转换为Observable

问题描述 投票:2回答:1

我有一个动态数组结构。具体来说,它是谷歌地图'MVCArray。这个结构有定期的put,get,remove方法,以及一个addListener来听取任何变化。库方法(Polygon#getPaths)返回LatLngs的MVCArray的MVCArray,因为多边形可以具有任意数量的路径,并且每个路径可以具有任意数量的顶点。

我的目标是转换生成一个观察到的PolygonPathEvent,它将在父MVCArray任何子MVCArray被更改时触发。

创建Observables

第一项业务是将addListener转换为Observables。

private createMVCEventObservable<T>(array: MVCArray<T>): Observable<[T[], string, number, T?]>{
    const eventNames = ['insert_at', 'remove_at', 'set_at'];
    return fromEventPattern(
      (handler: Function) => eventNames.map(evName => array.addListener(evName,
        (index: number, previous?: LatLng) => this._zone.run(() => handler.apply(array, [[array.getArray(), evName, index, previous]])))),
      (handler: Function, evListeners: MapsEventListener[]) => evListeners.forEach(evListener => evListener.remove()));
  }

结合Observables

现在结合起来,貌似我们需要使用combineLatest

const pathsChanges$ = this.createMVCEventObservable(paths);
const pathChanges$ = combineLatest(paths.getArray().map(this.createMVCEventObservable));
return combineLatest(pathChanges$, pathsChanges$, (pathArr, paths) => 
  new PolygonPathEvent(pathArr, paths);
);

问题是MVCArray的父MVCArray可以改变,但combineLatest接受静态数组。因此,当添加新路径时,我不知道如何使返回的Observable也听取这条新路径。同样,如果路径被删除,我不知道如何使返回的observable取消订阅已删除的路径。

管道到主题(错误的方法)

我想回到一个主题,只要父母MVCArray<MVCArray<LatLng>>改变就简单地将它订阅到不同的观察者。

const retVal: Subject<PolygonPathEvent> = new Subject();
const pathsChanges$ = this.createMVCEventObservable(paths);
const pathChanges$ = combineLatest(paths.getArray().map(this.createMVCEventObservable));
let latestSubscription = combineLatest(pathChanges$, pathsChanges$, (pathArr, paths) => 
  new PolygonPathEvent(pathArr, paths)
).subscribe(retVal);

pathsChanges$.pipe(tap( ([arrays, event, index, previous]) => {
  latestSubscription.unsubscribe();
  latestSubscription = combineLatest(pathChanges$, pathsChanges$, (pathArr, paths) => 
  new PolygonPathEvent(pathArr, paths)
  ).subscribe(retVal);
} ));

return retVal;

这是有效的,问题是对原始Observables(和addListener)的订阅恰好在此方法中发生,而不是在返回的Observable订阅时。

结论

我需要某种操作员。

rxjs reactivex
1个回答
1
投票

如果我理解你的问题,可能有空间使用switchMap来解决它。

你说“问题是MVCArray的父MVCArray可以改变,但combineLatest接受一个静态数组”。我认为你引用的静态数组是由pathChanges$ Observable发出的数组,它在代码片段的开头为所有人创建,并且在MVCArray的父MVCArray发生更改时不会更新。

如果我的理解是正确的,我们需要做的是提供一种方式来通知MVCArray的父MVCArray的更改事件,并且在任何这样的事件发生时,使用新的更新的数组再次执行combineLatest函数。

这可以通过类似于以下的逻辑来实现

const pathsChanges$ = this.createMVCEventObservable(paths);

pathsChanges$
.pipe(
   switchMap(() => combineLatest(paths.getArray().map(this.createMVCEventObservable))),
   map(pathArr => new PolygonPathEvent(pathArr, paths))
)

该逻辑假设变量paths从外部传递到这条逻辑中。

我无法重现这个案例,因此我很难确定我的答案能解决你的问题,即使我希望它有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.