【问题标题】:How can I do debounceTime but with the first value我怎样才能做 debounceTime 但第一个值
【发布时间】:2021-10-05 20:04:42
【问题描述】:

我有一个事件流,但我需要检测事件何时开始以及何时结束。

我希望这个大理石图会有所帮助

例如,当您按下按键时,触发了(S)。当我按住键时,没有任何事件发生。但是当我释放键时,50ms 后事件 (E) 正在触发

【问题讨论】:

    标签: typescript rxjs


    【解决方案1】:

    我认为这可能是一种方法:

    const customOperator = src$ => {
      let hasSentStartEvent = false;
    
      return src$.pipe(
        debounce(
          () => !hasSentStartEvent
            ? (hasSentStartEvent = true, timer(0, 50).pipe(skip(1), tap(() => hasSentStartEvent = false)))
            : timer(50).pipe(tap(() => hasSentStartEvent = false))
        ),
        map((_, idx) => idx % 2 === 0 ? 'S' : 'E'),
      )
    }
    
    src$.pipe(
      customOperator
    ).subscribe();
    

    我认为这是自定义运算符的情况,因为这种方法需要维护内部状态才能确定debounce 运算符处于哪个阶段。在我们的情况下,我们拥有的唯一状态是hasSentStartEvent,它指示是否已发送开始事件(在图中用S 表示)。

    debounce 运算符接受一个返回可观察对象的函数。返回的 observable 是否被订阅取决于来源(即src$)。如果源没有发出任何东西,那么 debounce 的内部 observable 将不会被订阅。
    一旦第一个值由源发送,调用提供的回调函数产生的内部 observable 将被订阅。当hasSentStartEvent 变量为false 时也是如此,因此将选择第一个if 分支。因此,S 事件将被发送,hasSentStartEvent 将被设置为 true。 如果源发出的下一个值在50ms pass(即计时器的值)之前,则将选择第二个 if 分支,因为我们自定义运算符的内部状态表明 @987654334 @ 事件已经发送。这里还需要提到的是,每次源发出时,内部的 observable 将被取消订阅(如果它是活动的),并且将通过调用回调函数创建一个新的 observable 并订阅它。
    最后,当50ms 通过而源没有发出任何值时,E(即 end) 事件将被发送,hasSentStartEvent 将被设置为false


    编辑

    再想一想,看起来debounce 的内部可观察对象将是automatically unsubscribed if it emits a value。因此,解决方案也可能是:

    const customOperator = src$ => {
      let hasSentStartEvent = false;
    
      return src$.pipe(
        debounce(
          () => !hasSentStartEvent
            // Just emitting a value immediately.
            ? (hasSentStartEvent = true, of(null))
            : timer(50).pipe(tap(() => hasSentStartEvent = false))
        ),
        map((_, idx) => idx % 2 === 0 ? 'S' : 'E'),
      )
    }
    
    src$.pipe(
      customOperator
    ).subscribe();
    

    【讨论】:

    • 一个优雅的解决方案,但是如果第一个事件已经发出而第二个事件没有发出,timer(50) 没有被执行,我不会得到流暂停的结果
    • @EvgenyNaumov 所以你指的是只发出一个值的情况?在这种情况下,您会期待一个S 事件,然后在50ms 一个E 事件,对吧?
    • 是的,这正是我所期望的
    猜你喜欢
    • 2019-09-01
    • 1970-01-01
    • 2021-04-13
    • 1970-01-01
    • 2021-10-25
    • 2014-01-03
    • 1970-01-01
    • 2022-11-09
    • 2011-09-03
    相关资源
    最近更新 更多