Реактивное программирование: как подписаться и отобрать источник событий? - PullRequest
0 голосов
/ 05 февраля 2019

Я отправляю сообщение источнику событий в приложении React Native, которое потребляет act-native-ble-manager .

handleUpdateValueForCharacteristic(data) {

    console.log('Received data from ' + data.peripheral + ' characteristic ' + data.characteristic, data.value);

  }
bleManagerEmitter.addListener('BleManagerDidUpdateValueForCharacteristic', this.handleUpdateValueForCharacteristic );

Я имею дело с событием BluetoothПоток с частотой 50, 100 или 200 событий в секунду (Гц).

Меня интересуют все события на частоте 50 Гц, половина из них на частоте 100 Гц и четверть на частоте 200 Гц.Как правильно подписаться на это событие Stream с помощью RxJS и какой оператор следует использовать для выборки данных?

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

1 Ответ

0 голосов
/ 05 февраля 2019

fromEventPattern должно быть тем, что вы ищете.

Это позволяет вам создавать наблюдаемые на основе пользовательских событий (например, что вы получили с этим менеджером BLE).

Ниже приведен фрагмент с описанием того, как вы можете его использовать.

Обратите внимание на комбинацию scan() и filter().Используя прежний оператор для отслеживания события n th , он эффективно изменяет частоту, с которой события отбираются и обрабатываются любыми подписчиками.

В вашем сценарии вы будетехотите, чтобы scan() также отслеживал испускаемое событие, чтобы в конечном итоге вы могли map() его после вызова filter(), чтобы подписчики получали его.Ключевым моментом здесь является отслеживание состояния события в пределах scan() (т. Е. Свойства тика и данных события, t и data в фрагменте соответственно) по мере накопления событий.

const { fromEventPattern } = rxjs;
const { filter, map, scan } = rxjs.operators;

// Tweak parameters to vary demo
const hz = 200;
const sample = 4;

function addEmitterHandler(handler) {
  // bleManagerEmitter.addListener('event', handler)
  const intervalId = setInterval(() => {
    handler({ timestamp: Date.now() });
  }, 1000 / hz);
  return intervalId;
}

function removeEmitterHandler(handler, intervalId) {
  // bleManagerEmitter.removeListener(...)
  clearInterval(intervalId);
}

// Simulate emissions using the `setInterval()` call
const emitter = fromEventPattern(
  addEmitterHandler,
  removeEmitterHandler
);

emitter.pipe(
  // Use `scan()` and `filter()` combination to adjust sampling
  scan((state, data) => {
    const t = (state.t % (sample + 1)) + 1;
    return { t, data };
  }, { t: 0, data: null }),
  filter(state => state.t % sample === 0),
  // Use `map()` to forward event data only
  map(state => state.data),
).subscribe(data => console.log(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>
...