【问题标题】:RxJS: Change throttleTime after X emissionsRxJS:X 排放后更改节流阀时间
【发布时间】:2019-09-17 05:18:03
【问题描述】:

我正在构建一个 RxJS 幻灯片,如果用户按住右箭头键,我想每 500 毫秒导航到下一个图块。我正在使用throttleTime,如下所示:

const forwardNavigation$ = fromEvent(document, 'keydown').pipe(
    filter(event => event.keyCode === KEY_CODE.arrowRight),
    throttleTime(500)
);

我现在想做的是在不释放箭头键的情况下导航到第 5 个图块后将 throttleTime 减少到 100 毫秒。

这可能吗,如何实施?

【问题讨论】:

    标签: javascript rxjs reactive-programming


    【解决方案1】:

    如果您想要一种仅使用 Observable 的更具声明性的方法,以下方法也可以:

    const source$ = fromEvent(document, 'keydown').pipe(
      filter((event: KeyboardEvent) => event.code === "ArrowRight")
    );
    const slow$ = source$.pipe(throttleTime(500), take(5));
    const fast$ = source$.pipe(throttleTime(100));
    
    const forwardNavigation$ = concat(slow$, fast$);
    // subscribe to forwardNavigation$ and execute navigation code
    

    这样做是根据键盘事件创建两个具有不同油门时间的 Observable。然后它使用concat 合并两者的结果,这将忽略第二个,直到第一个完成。将 take(5) 添加到第一个 observable 意味着它在 5 次发射后完成,此时 fast$ Observable 接管。

    工作StackBlitz

    【讨论】:

    • 谢谢,这正是我想要的!作为 RxJs 的初学者,我什至无法想象如何解决这个问题,您的代码和解释让我对它有了深刻的见解!
    • 顺便说一句,既然你提到你是 rxjs 的新手,这种拆分源 Observable、在每个“分支”上执行不同操作然后合并结果的模式是我反复使用的模式. Here 是一篇很好的文章来解释这种模式。
    【解决方案2】:

    您可以使用throttle 运算符并返回适当的interval observable。请参考以下示例:

    import {fromEvent, interval} from 'rxjs';
    import {filter, throttle} from 'rxjs/operators';
    
    let iteration = 1;
    
    const forwardNavigation$ = fromEvent(document, 'keydown').pipe(
        filter(event => event.keyCode === 13),
        throttle(() => iteration++ % 5 === 0 ? interval(100) : interval(500))
    );
    
    forwardNavigation$.subscribe(console.log)
    

    可以在here 找到工作演示。按下Enter 键的同时观察控制台。

    【讨论】:

    • 谢谢,这很有帮助!我只是想知道,是否可以避免全局变量iteration
    • iteration这里本质上是指当前幻灯片的数量,5是幻灯片的总数。如果你可以用另一组变量来设计它们,它也应该可以工作。
    【解决方案3】:

    为了完整起见,这是基于@dmcgrandle 答案的最终代码:

    import { fromEvent, concat } from 'rxjs';
    import { filter, throttleTime, take, skip, startWith, switchMap } from 'rxjs/operators';
    
    const keyboardRightKey$ = fromEvent(document, 'keydown').pipe(
        filter(e => e.keyCode === 39)
    );
    
    fromEvent(document, 'keyup').pipe(
        startWith(true),
        switchMap(() => concat(
          keyboardRightKey$.pipe(throttleTime(500), take(5)),
          keyboardRightKey$.pipe(throttleTime(100), skip(1))
        ))
    );
    

    我添加了另一个位来重置每个keyup 上的流,然后使用它的RxVIZ to create a visualization

    【讨论】:

    • 给这只猫剥皮的方法很多。这是另一个使用高阶 Observables 的方法:of( source$.pipe(throttleTime(500), take(5)), source$.pipe(throttleTime(100)) ).pipe(concatAll())。 StackBlitz here
    猜你喜欢
    • 1970-01-01
    • 2020-08-02
    • 1970-01-01
    • 1970-01-01
    • 2022-10-20
    • 2021-12-10
    • 2019-10-03
    • 2020-01-22
    • 2017-03-22
    相关资源
    最近更新 更多