Отмените наблюдаемое, созданное с помощью «fromEvent», и переключитесь на новое. - PullRequest
1 голос
/ 13 июня 2019

Моя цель состоит в том, чтобы издавать «привет снова» с интервалом в 1 секунду, пока не будет нажата клавиша, и продолжать работу при каждом щелчке мыши. Вот мой код:

import { of, fromEvent, interval } from 'rxjs'; 
import { map, tap, takeUntil,take, repeatWhen, shareReplay, switchMap , takeLast} from 'rxjs/operators';

const fromKeyUp$ = fromEvent(window, 'keyup').pipe(tap(_=> console.log('keyup')));

const fromMouseUp$ = fromEvent(window, 'mouseup').pipe(tap(_=> console.log('mouseup')));

const source = interval(1000).pipe(tap(_ => {
  console.log('hi again');
}), takeUntil(fromKeyUp$), repeatWhen(() => fromMouseUp$));

source.subscribe();

Проблема в том, что при слишком большом количестве щелчков мышью => «снова снова» издает больше раз, чем обычно.

Я пытался использовать switchMap, чтобы отменить предыдущую мышиную, например:

const fromMouseUp$ = fromEvent(window, 'mouseup').pipe(switchMap(() => tap(_=> console.log('mouseup'))));

но это не сработало, так как тап не предназначен для создания.

Есть идеи?

Ответы [ 3 ]

2 голосов
/ 13 июня 2019

Я думаю, вы можете просто изменить порядок операторов и использовать switchMap для отмены предыдущего interval:

fromMouseUp$.pipe(
  startWith(null),
  switchMap(() => interval(1000).pipe(
    takeUntil(fromKeyUp$),
  )),
).subscribe();
1 голос
/ 13 июня 2019

Приведенный ниже код будет переключать значение через mouseup или останавливаться с помощью keyup, вы можете поместить свою логику обработки в mergeMap

const fromKeyUp$ = fromEvent(window, 'keyup').pipe(tap(_=> console.log('keyup')),mapTo(false));

const fromMouseUp$ = fromEvent(window, 'mouseup').pipe(tap(_=> console.log('mouseup')),mapTo(true));

const timeInterval=interval(1000).pipe(
  tap(_ => {
  console.log('hi again');
}))

const source=combineLatest(timeInterval,merge(fromMouseUp$,fromKeyUp$).pipe(startWith(true))
).pipe(
   mergeMap(([value,through])=>through? 
     of(value):never()),distinctUntilChanged() 
 )

source.subscribe(console.log);

другая более простая альтернатива с windowToggle

interval(2000).pipe(
  windowToggle(fromMouseUp$.pipe(startWith(true)),()=>fromKeyUp$),
  switchMap(obs=>obs)
).subscribe(console.log)

оба решения не будут прерывать исходный интервал

0 голосов
/ 13 июня 2019

Используйте switchMap для переключения на нужный источник из объединенного потока событий pause и resume.

import { interval, fromEvent, merge, EMPTY } from 'rxjs';
import { switchMap, startWith, mapTo, tap } from 'rxjs/operators';

const source$ = interval(1000).pipe(tap(_ => console.log('Hi again')));

const pause$ = fromEvent(window, 'keyup').pipe(
  tap(_ => console.log('keyup')),
  mapTo(false)
);
const resume$ = fromEvent(window, 'mouseup').pipe(
  tap(_ => console.log('mouseup')),
  mapTo(true)
);

const notification$ = merge(pause$, resume$).pipe(
  // add startWith(true) if the source should start emitting on subscribe, 
  // remove it if the source should only start on 'mouseup'
  startWith(true), 
  switchMap(val => (val ? source$ : EMPTY)),
)

notification$.subscribe();

https://stackblitz.com/edit/typescript-4zgnbn

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...