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>