我的目标是在1秒钟的间隔内发出“ hi hi”(直到再次发出声音),直到按键被按下为止,并在每次单击鼠标时继续发出声音。 这是我的代码:
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();
问题在于,当鼠标单击次数过多时,=>“ hihi”发出的次数比平时多。
我尝试使用switchMap
来取消以前的mouseup提示,例如:
const fromMouseUp$ = fromEvent(window, 'mouseup').pipe(switchMap(() => tap(_=> console.log('mouseup'))));
但是它不起作用,因为Tap并非用于创建。
有什么想法吗?
答案 0 :(得分:2)
我认为您可以对运算符重新排序并使用switchMap
来取消先前的interval
:
fromMouseUp$.pipe(
startWith(null),
switchMap(() => interval(1000).pipe(
takeUntil(fromKeyUp$),
)),
).subscribe();
答案 1 :(得分:1)
下面的代码将通过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)
两种解决方案都不会中断源间隔
答案 2 :(得分:0)
使用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();