Преобразовать динамический массив динамических массивов в наблюдаемые - PullRequest
2 голосов
/ 16 марта 2019

У меня есть структура динамического массива.В частности, это Google Maps ' MVCArray .Эта структура имеет обычные методы put, get, remove, а также addListener для прослушивания любых изменений.Библиотечный метод (Polygon # getPaths) возвращает MVCArray из MVCArray из LatLngs, поскольку у многоугольника может быть любое количество путей, и каждый путь может иметь любое количество вершин.

Моя цель - преобразовать сгенерировать Observable из 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()));
  }

Объединение наблюдаемых

Теперь для объединения, по-видимому, нам нужно использовать 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.

Заключение

Мне нужен какой-то оператор для этого.

1 Ответ

1 голос
/ 19 марта 2019

Если я правильно понимаю вашу проблему, возможно, есть место для использования switchMap для ее решения.

Вы говорите, что " Проблема в том, что родительский MVCArray из MVCArray может измениться, но закомментировать последнийпринимает статический массив".Я думаю, что статический массив, на который вы ссылаетесь, - это тот, который генерируется 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 передается в этот фрагмент логики извне.

Я не смог воспроизвести случай, и поэтому я не уверен, что мой ответ решит вашу проблему, даже если я надеюсь, что это поможет.

...