Javascript 先发出值,然后忽略计时器内发出的值
这是我的代码:Javascript 先发出值,然后忽略计时器内发出的值,javascript,angular,rxjs,observable,Javascript,Angular,Rxjs,Observable,这是我的代码: 应用程序组件.ts notifier$ = new BehaviorSubject<any>({}); notify() { this.notifier$.next({}); } <div (scroll)="notify()"></div> <child-component [inp]="notifier$ | async" /> 但是我想用rxjs来做这件事。然而,debounceTime与我想要的正好相反,而且thr
应用程序组件.ts
notifier$ = new BehaviorSubject<any>({});
notify() {
this.notifier$.next({});
}
<div (scroll)="notify()"></div>
<child-component [inp]="notifier$ | async" />
但是我想用rxjs
来做这件事。然而,debounceTime
与我想要的正好相反,而且throttleTime
和auditTime
都不是我想要的。有办法吗?您可以使用take(1)
take(1)只取第一个值并完成。不涉及进一步的逻辑
当然,您应该在子组件中使用上述内容:)
此外,由于您的可观察对象正在完成…您可以创建一个新的主题,并在每次子组件滚动时将其传递给子组件
notify() {
this.notifier$ = new BehaviorSubject<any>({});
this.notifier$.next({});
}
通知(){
this.notifier$=新行为子对象({});
this.notifier$.next({});
}
当用户滚动时,您希望为每个滚动事件通知$
。这提供了一个恒定的发射值流。因此,您希望通知程序$
在流启动时发出一次,在流空闲1秒时再次发出
notify$=新主题();
通知程序$=合并(
通知$.pipe(first()),
通知$.pipe(开关映射(值=>of(值).pipe(延迟(1000)))
).管道(
以(2)为例,
重复()
);
你合并了两个观测值。第一个会立即发射,第二个会在1秒延迟后发射。您可以使用开关映射,以便始终重新启动延迟的可观察对象
我们获取触发流完成的下2个值,并使用repeat重新开始。您可以构建如下可观察值:
const scroll$ = fromEvent(document, 'scroll');
const scrollEnd$ = scroll$.pipe(
switchMapTo(
timer(1000) // on every scroll, restart a timer
)
);
const scrollStart$ = scrollEnd$.pipe( // the scroll end event triggers switch to scroll$
startWith(0), // but start it off
switchMapTo(
scroll$.pipe( // then just take the first scroll$ event
first()
)
)
);
scrollStart$.subscribe(v => console.log('scroll start'));
您可以将其推广到运算符:
function firstTimeout(timeout: number) { // welcoming notes on a better name
return input$ => {
const inputTimeout$ = input$.pipe(
switchMapTo(timer(timeout))
);
return inputTimeout$.pipe(
startWith(0),
switchMapTo(input$.pipe(first()))
);
};
}
然后像这样使用它:
notifier$.pipe(firstTimeout(1000)).subscribe(v => console.log('took one'));
对于这种情况,一个好主意可能是将其包装在一个指令中以便于重用:
@Directive({
selector: '[scrollStart]'
})
export class ScrollStartDirective {
private scrollSource = new Subject();
@HostListener('scroll', ['$event'])
private onScroll(event) {
this.scrollSource.next(event);
}
@Output()
scrollStart = new EventEmitter();
constructor() {
this.scrollSource.pipe(firstTimeout(1000)).subscribe(this.scrollStart);
}
}
然后你可以这样使用它:
<div (scrollStart)="notify()"></div>
我想在用户每次滚动时获取第一个值,而不是一次。如果用户停止滚动,然后再次开始滚动,我想再次发出。您是否可以尝试使用takeUntil()这不起作用,当用户滚动时,notify()
会被重复调用。用户开始滚动,因此会调用notify()
,然后你想忽略其他调用直到调用停止1秒吗?@Reactgular Yes这似乎与debounceTime
做的事情相同,只要用户滚动,它就不会发出第二次。这是正确的解决方案……我建议使用take(1)而不是first(),因为如果用户从不滚动,那么就使用first()会在你的控制台上抛出一个错误!我要添加的唯一内容是在directive@obl你可以但不必。。。是本地的subject@bryan60嗯,我不知道什么时候需要退订。这与在组件中使用.subscribe
有什么区别?@obl我在这里写了一个答案:
@Directive({
selector: '[scrollStart]'
})
export class ScrollStartDirective {
private scrollSource = new Subject();
@HostListener('scroll', ['$event'])
private onScroll(event) {
this.scrollSource.next(event);
}
@Output()
scrollStart = new EventEmitter();
constructor() {
this.scrollSource.pipe(firstTimeout(1000)).subscribe(this.scrollStart);
}
}
<div (scrollStart)="notify()"></div>