Как фильтровать каждый массив, возвращаемый наблюдаемым массивом - PullRequest
1 голос
/ 11 марта 2020

У меня есть метод, который возвращает устройства, и я вижу, что он возвращает 2 устройства:

public getDevices(): Observable<Array<Device>> {
  return this.state$
    .pipe(
      map((devices: Array<Device>) => {
        return devices
      })
    );
}

Но если я добавлю фильтр для элементов массива, он вообще не отобразит устройства:

public getDevices(): Observable<Array<Device>> {
  return this.state$
    .pipe(
      map((devices: Array<Device>) => {
        return devices
          .filter((device: Device) => {
            return device != null && device.mute != true
          })
      }),
    );
}

То же самое для жестко закодированного фильтра истинности:

public getDevices(): Observable<Array<Device>> {
  return this.state$
    .pipe(
      map((devices: Array<Device>) => {
        return devices
          .filter((device: Device) => {
            return true
          })
      }),
    );
}

Я также пробовал со следующим, и все равно он не отображает никаких устройств:

public getDevices(): Observable<Array<Device>> {
  return this.state$
    .pipe(
      map((devices: Array<Device>) => {
        devices = devices.filter((device: Device) => {
          return device != null && device.mute != true
        })
        return devices;
      }),
    );
}

Это показывает не пустые массивы в логгере:

public getDevices(): Observable<Array<Device>> {
  return this.state$
    .pipe(
      tap((devices: Array<Device>) => {
        console.log(devices);
      }),
      // map((devices: Array<Device>) => {
      //   return devices
      //     .filter((device: Device) => {
      //       return device != null && device.mute != true
      //     })
      // }),
    );
}

Содержимое консоли браузера:

(2) [Device, Device]
0: Device
id: "MidiThroughPort-0"
name: "Midi Through Port-0"
mute: false
midiMessageSubscription: Subscriber {closed: false, _parentOrParents: null, _subscriptions: Array(1), syncErrorValue: null, syncErrorThrown: false, …}
synth: s.default.PolySynth {_context: s.d…t.Context, output: s.d…t.Volume, _volume: s.d…t.Volume, volume: s.d…t.Param, _scheduledEvents: Array(0), …}
keyboard: Piano {_events: {…}, _maxListeners: undefined, type: "Piano", parent: div#keyboard-device-MidiThroughPort-0, width: 500, …}
__proto__: Object
1: Device {id: "VMPKOutput", name: "VMPK Output", mute: false, midiMessageSubscription: Subscriber, synth: s.d…t.PolySynth, …}
length: 2

Но раскомментированный закомментированный код как:

public getDevices(): Observable<Array<Device>> {
  return this.state$
    .pipe(
      tap((devices: Array<Device>) => {
        console.log(devices);
      }),
      map((devices: Array<Device>) => {
        return devices
          .filter((device: Device) => {
            return device != null && device.mute != true
          })
      }),
    );
}

делает регистратор, да тот же самый регистратор, теперь показывает пустой массив: []

Одна очень странная вещь состоит в том, что, когда я комментирую код фильтра, регистратор вызывается только один раз, один раз пустой [] И когда я раскомментирую код фильтра, вышеуказанный регистратор вызывается 5 раз, сначала пустой [], а затем 4 раза непустой (2) [Device, Device]

Вот как я могу добавить устройство:

public addDevice(device: Device) {
  const index = this.getDeviceIndex(device.id);
  if (index === -1) {
    device.id = this.commonService.normalizeName(device.id);
    this.getState().push(device);
  }
}

с состоянием:

export class Store<T> {

  state$: Observable<T>;
  private _state$: BehaviorSubject<T>;

  protected constructor(initialState: T) {
    this._state$ = new BehaviorSubject(initialState);
    this.state$ = this._state$.asObservable();
  }

  public getState(): T {
    return this._state$.getValue();
  }

  public setState(nextState: T) {
    this._state$.next(nextState);
  }

}

ОБНОВЛЕНИЕ: Наблюдаемое не было уведомлено любого изменения, когда pu sh другой элемент к его значению массива. Поэтому я создал еще один метод в классе Store, который перезагружает наблюдаемое:

public reloadState() {
  this._state$.next(this._state$.getValue());
}

Я вызываю этот метод после нажатия другого элемента в массиве устройств:

public addDevice(device: Device) {
  const index = this.getDeviceIndex(device.id);
  if (index === -1) {
    device.id = this.commonService.normalizeName(device.id);
    this.getState().push(device);
    this.reloadState();
  }
}
...