我有一个动态数组结构。具体来说就是Google Maps的MVCArray。该结构具有常规的put,get,remove方法以及一个addListener
来侦听任何更改。库方法(Polygon#getPaths)返回LatLngs的MVCArray的MVCArray,因为多边形可以具有任意数量的路径,并且每个路径可以具有任意数量的顶点。
我的目标是转换生成PolygonPathEvent
的Observable,当父MVCArray或任何子MVCArray更改时将触发。
首要业务是将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()));
}
现在要合并,看来我们需要使用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也监听此新路径。同样,如果删除了路径,我不知道如何使返回的可观察者从已删除的路径退订。
我考虑过返回一个主题,并且只要父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时发生。
为此我需要某种运算符。
答案 0 :(得分: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
从外部传递到此逻辑中。
我无法重提此案,因此即使我希望能对您有所帮助,我也不确定我的答案是否可以解决您的问题。