【问题标题】:How to use RxJS to display a "user is typing" indicator?如何使用 RxJS 显示“用户正在输入”指示器?
【发布时间】:2017-05-22 02:44:04
【问题描述】:

我对 BaconJS 有所了解,但现在我正在尝试通过创建“用户正在输入...”指示器来学习 RxJS。很简单,可以用两条简单的规则来解释:

  1. 当用户输入时,指示器应该立即可见。
  2. 当用户停止输入时,指示器应该仍然可见,直到用户最后一次输入操作后 1 秒。

我不确定这是否正确,但到目前为止我已经创建了两个流:

  1. 一个心跳流,每秒发出一个0
  2. 一个流用于捕获用户键入事件并为每个事件发出一个1

然后我将它们合并在一起,然后简单地挖掘结果。如果是1,那么我会显示指标。如果是0,那么我隐藏指示器。

看起来是这样的:

const showTyping = () =>
  $('.typing').text('User is typing...');

const showIdle = () =>
  $('.typing').text('');

// 1 second heartbeats are mapped to 0
const heartbeat$ = Rx.Observable
  .interval(1000)
  .mapTo(0);

// user typing events are mapped to 1
const input$ = Rx.Observable
  .fromEvent($('#input'), 'input')
  .mapTo(1);

// we merge the streams together
const state$ = heartbeat$
  .merge(input$)
  .do(val => val === 0 ? showIdle() : showTyping())
  .subscribe(console.log);

这里是 JSBin 的链接:

http://jsbin.com/vekixuv/edit?js,console,output

我对这个实现有几个问题和疑问:

  1. 有时,当用户键入时,0 会偷偷溜进来,因此指示器会闪烁一秒钟,然后在用户下一次击键时再次出现。
  2. 不保证指示符会在用户停止输入 1 秒后消失。只能保证指示器会在 1 秒内消失(这与我们想要的相反)。
  3. 使用心跳流是正确的 RxJS 方法吗?我感觉可能不是。

我觉得我的实现完全脱离了基础,感谢您提供的任何帮助。谢谢。

【问题讨论】:

    标签: javascript rxjs rxjs5 rxjs-dom


    【解决方案1】:

    你不需要心跳,只要有事情发生/变化就发出变化事件:

    const showTyping = () =>
      $('.typing').text('User is typing...');
    
    const showIdle = () =>
      $('.typing').text('');
    
    
    // user typing events
    const input$ = Rx.Observable
      .fromEvent($('#input'), 'input');
    
    // user stopped typing
    const stoppedTypingAfter1s$ = input$
      .switchMapTo(Rx.Observable.timer(1000));
    
    // we merge the streams together
    const state$ = Rx.Observable.merge(
        input$.mapTo(1),
        stoppedTypingAfter1s$.mapTo(0)
    )
      .startWith(0)
      .do(val => val === 0 ? showIdle() : showTyping())
      .subscribe(console.log);
    

    观看直播here

    switchMap 会在发出新的打字事件时丢弃任何之前的 1 秒计时器。

    【讨论】:

    • 虽然我选择了另一个答案,但这对于理解如何使用 switchMap 来发出“更改”事件也很有帮助。
    【解决方案2】:

    您甚至不需要使用两个 Observable,只需使用一个 debounceTime()。您尝试制作的所有逻辑都已存在于debounceTime() 运算符中:

    const showTyping = () =>
      $('.typing').text('User is typing...');
    
    const showIdle = () =>
      $('.typing').text('');
    
    const input$ = Rx.Observable
      .fromEvent($('#input'), 'input')
      .do(() => showTyping())
      .debounceTime(1000)
      .subscribe(() => showIdle());
    

    观看现场演示:http://jsbin.com/cixipa/6/edit?js,console,output

    【讨论】:

      猜你喜欢
      • 2012-02-18
      • 2017-03-05
      • 2020-09-30
      • 2021-09-24
      • 2021-09-28
      • 2020-02-14
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多