6

私は BaconJS を少し知っていますが、今は「ユーザーが入力中です...」インジケーターを作成して RxJS を学ぼうとしています。それは非常に単純で、2 つの単純なルールで説明できます。

  1. ユーザーが入力しているときに、インジケーターがすぐに表示される必要があります。
  2. ユーザーが入力を止めても、ユーザーの最後の入力アクションから 1 秒後までインジケーターが表示されたままになる必要があります。

これが正しいかどうかはわかりませんが、これまでに 2 つのストリームを作成しました。

  1. 1 秒ごとに を発行する 1 つのハートビート ストリーム0
  2. ユーザー入力イベントをキャプチャし、1for every イベントを発行する 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,コンソール,出力

この実装にはいくつかの問題と質問があります。

  1. ユーザーが入力しているときに、が0こっそり通り抜けることがあるため、次のユーザーのキーストロークに戻る前に、インジケーターが一瞬点滅します。
  2. ユーザーが入力を停止してから 1 秒後にインジケーターが消えることは保証されていません。インジケーターが 1 秒以内に消えることが保証されているだけです (これは、私たちが望むものとは逆です)。
  3. これを行うには、ハートビート ストリームを使用するのが RxJS の正しい方法ですか? そうじゃないかもって感じ。

私は自分の実装に完全にずれていると感じています。あなたが提供できるかもしれない助けに感謝します。ありがとう。

4

2 に答える 2

10

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

于 2017-01-07T11:39:04.303 に答える
4

これにはハートビートは必要ありません。何かが発生/変更するたびに変更イベントを発行するだけです:

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);

ここでライブを参照してください。

switchMap、新しい入力イベントが発行されるたびに、以前の 1 秒タイマーを破棄します。

于 2017-01-07T11:34:08.073 に答える