【问题标题】:Reset Scan Accumulator RxJS after certain time一定时间后重置扫描累加器 RxJS
【发布时间】:2020-09-08 15:38:36
【问题描述】:

我有一个 fromEvent 附加到输入 keydown 事件。这样我就可以监听 KeyEvents。

在管道内部,我使用了scan算子,所以可以累积用户最近引入的3个key。

我检查了扫描,累加器长度,所以如果它已经是三个,我清理它(手动重置)。

我需要一种方法,当用户输入时,在接下来的 3000 毫秒内,他可以继续输入直到达到限制(3 个键)但如果用户慢于时间限制(3 秒),下次他输入,我会手动重置累加器。

  fromEvent(myInput.nativeElement, 'keydown').pipe(
    tap(e => e.preventDefault()),
    scan((acc: KeyboardEvent[], val: KeyboardEvent) => {
      // Add condition here to manually reset the accumulator...
      if (acc.length === 3) {
        acc = [];
      }
      return [...acc, val];
    }, []),
    takeUntil(this.destroy$)
  ).subscribe((events: KeyboardEvent[]) => console.log(events));

我试图以某种方式将它与计时器合并,但我不知道如何。不知道怎么去那里。

【问题讨论】:

  • 我在这里很困惑。您想在 3 次击键或 3 秒时重置累加器,以先到者为准?
  • 正是@bryan60 - 我将添加您的评论,因为它恢复了我在这里的目标。谢谢。
  • 每次按键都会重置 3 秒计时器吗?
  • 是的。只是一个小细节,它支持 3 次击键,当累加器为 3 并进入扫描时,它是第 4 次,所以我们重置并添加一个作为新结果的第一个值。

标签: rxjs rxjs-pipeable-operators


【解决方案1】:

您可以在此处使用timeInterval 运算符,它会为您提供发射之间经过的时间以及值。设置如下:

  fromEvent(myInput.nativeElement, 'keydown').pipe(
    tap(e => e.preventDefault()),
    timeInterval(), // just add this operator, will convert to shape {value: T, interval: number}
    scan((acc: KeyboardEvent[], val) => {
      // Add condition here to manually reset the accumulator...
      // also check the interval
      if (acc.length === 3 || val.interval > 3000) {
        acc = [];
      }
      return [...acc, val.value];
    }, []),
    takeUntil(this.destroy$)
   ).subscribe((events: KeyboardEvent[]) => console.log(events));

这是一个有效的闪电战:https://stackblitz.com/edit/rxjs-dxfb37?file=index.ts

不是我以前有过用例的运算符,但似乎在这里非常有效地解决了您的问题。

【讨论】:

  • 可能,这个 if 语句应该返回空数组而不是赋值 if (acc.length === 3 || val.interval > 3000) { return []; }
  • @a_zatula 我不相信这就是 OP 想要的。我认为如果超过 3 秒,它应该重置数组并发出新值
  • 它就像一个魅力,这正是我想要的,非常感谢。顺便说一句,我添加了类型: (val: TimeInterval) => {...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-29
  • 2019-10-13
  • 1970-01-01
相关资源
最近更新 更多