如何使用RxJS显示“用户正在打字”指示?

时间:2017-01-07 11:25:01

标签: javascript rxjs rxjs5 rxjs-dom

我知道一点BaconJS,但现在我正在尝试通过创建“用户输入...”指示器来学习RxJS。这很简单,可以用两个简单的规则来解释:

  1. 当用户输入时,指示符应立即可见。
  2. 当用户停止输入时,指示符应该在用户上次输入操作后1秒钟仍然可见。
  3. 我不确定这是否正确,但我到目前为止已创建了两个流:

    1. 每秒发出一次0的心跳流。
    2. 用于捕获用户键入事件并为每个事件发出1的一个流。
    3. 然后我将它们合并在一起,然后简单地点击结果。如果它是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方式来做到这一点?我感觉可能不是。
      4. 我觉得我完全偏离了我的实施,我感谢您提供的任何帮助。感谢。

2 个答案:

答案 0 :(得分:7)

您甚至不需要使用两个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

答案 1 :(得分:3)

你不需要心跳,只要在事情发生/发生变化时发出变更事件:

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,每当发出新的输入事件时,都会丢弃任何prevouse 1s-timer。