Отслеживание активности мыши RxJS - PullRequest
0 голосов
/ 04 июня 2018

Я занимаюсь разработкой системы отслеживания активности пользователей и пытаюсь достичь следующих целей:

  1. Поймать событие mousemove раз в две секунды пользователь начал двигать мышь.
  2. Поймать моментчерез две секунды пользователь закончил движение мышью.

У меня есть следующие потоки:

const activityStream$ = Rx.Observable.fromEvent(document, 'mousemove');

const enterActivityStream$ = activityStream$.throttleTime(1000).skip(2);

const finishActivityStream$ = activityStream$.debounceTime(2000);

Отдельно они работают как положено, и я хотел бы объединить их, поэтому они будут работать в повторном режимеманера.

Например: пользователь начал перемещать мышь, через две секунды наблюдатель получает событие об этом (или, по крайней мере, оператор do), затем пользователь заканчивает перемещение мыши, и наблюдатель также получает уведомление об этом.Если пользователь снова начал двигать мышь, эта процедура повторялась.

Я нашел там аналогичный вопрос Пример RxJS Наблюдаемый, когда активность мыши или щелчка перезапускается , но решение кажется сложным и не работает какпредназначена.(lastact$ поток запускается дважды, когда он должен срабатывать один раз).

Пожалуйста, кто-нибудь может дать мне подсказку о том, как мне этого добиться?Спасибо!

Ответы [ 3 ]

0 голосов
/ 04 июня 2018

Благодаря Мартину .Наконец я смог достичь желаемого решения.Это работает, но я буду признателен за любые советы по улучшению этого кода.

const activityStream$ = Rx.Observable.fromEvent(document, 'mousemove').mapTo(true);

const enterActivityStream$ = activityStream$
  .throttleTime(2000)
  .skip(1) // Skip first event to avoid accidental touches
  .takeUntil(activityStream$.debounceTime(100)) // reset after 100 milliseconds of inactivity
  .repeat(); // and then repeat

const finishActivityStream$ = activityStream$.debounceTime(2000).mapTo(false);


enterActivityStream$
  .mergeMap(() => activityStream$.merge(finishActivityStream$)) 
  .distinctUntilChanged()
  .take(2) // Take true (activity started) and then false (activity stopped).
  .repeat() // And then repeat
  .subscribe(active => {
    if (active) {
      console.log('Notify about activity being started');
    } else {
      console.log('Notify about activity being stopped');
    }
  })
0 голосов
/ 24 февраля 2019

Посмотрите на это решение на stackblitz , если вы все еще ищете

import { interval, fromEvent } from 'rxjs';
import { throttle, tap, debounceTime, delay } from 'rxjs/operators';

const source = fromEvent(document, 'mousemove');

const untilIsActiv = source.pipe(
  debounceTime(2000),
  tap(val => console.log(`caugth inactivity`))
);

const example = source
  .pipe(
    delay(2000),
    throttle(val => untilIsActiv)
  );


const subscribe = example.subscribe(val => console.log('caugth event'));
0 голосов
/ 04 июня 2018

Я думаю, что вы можете использовать только merge:

Observable.merge(
    enterActivityStream$, 
    activityStream$, 
    finishActivityStream$,
  )
  .subscribe(...)

Из вашего описания похоже, что вы хотите начать испускать любые значения только после интервала 2 с, так что вы можете сделать это так:

enterActivityStream$
  .take(1)
  .mergeMap(() => activityStream$)
  .takeUntil(finishActivityStream$)
  .repeat()
  .subscribe(...);
...