Подсчет нажатий клавиш в секунду с угловым 2 Rxjs

/**
 * Created by darius on 02/04/16.
 */
import { Component } from 'angular2/core';
import { Observable } from 'rxjs/Rx';


@Component({
  styles: [ require('../../style.css') ],
  selector: 'keypresses-per-second',

  template: `

    <div class="block">

      <input  type="text" (keypress)="onKeypress($event)">

      {{keypresses}} <br>
      <input type="text" (keypress)="onKeypressReact($event)">
      {{keypressesReactive}}
    </div>
  `
})

export class KeypressesPerSecond {

  ngOnInit() {

    this.nonReactive();

    this.reactiveWay();
  }

  // not reactive
  keypresses = '';
  counter = 0;
  secondsPassed = 0;

  nonReactive(){

    var self = this;

    var int = setInterval(function(){

      console.log(self.counter, 'counter in non reactive')
      self.keypresses += self.counter + ', ';
      self.counter = 0;
      self.secondsPassed++
      if (self.secondsPassed > 30) {
        clearInterval(int);
      }
    }, 1000);
  }

  onKeypress($event){
    console.log($event.keyCode);
    this.counter++;
  }
  // end not reactive

  onKeypressReact() {}

  keypressesReactive = '';
  reactiveCount = 0;

  reactiveWay() {

    console.log('reactive way')

    const keypressObservable$ = Observable.create(observer => {

      // from template
      this.onKeypressReact = () => { observer.next('press'); };
    });


    keypressObservable$.subscribe(function(event) {
      self.reactiveCount++;
    });

    var self = this;

    var timer$ = Observable.create(function(observer){

      // is subscribed to this observable
      var subscribed = true;
      var int = setInterval(function() {

        if (subscribed) {
          observer.next(self.reactiveCount);
          self.reactiveCount = 0;
        }

        if (self.secondsPassed > 30) {
          observer.complete();
          clearInterval(int)
        }

      }, 1000);

    })


    timer$.subscribe(
      function (x) {
        console.log('Nextzz: %s', x);
        self.keypressesReactive += x + ', ';
      });

  }

}

Я пытался написать реактивный и нереактивный способ счетчика нажатий клавиш. Взгляните на функцию reactiveWay()

это работает, но я думаю, что может быть что-то не так.

Я делал там упражнения http://reactivex.io/learnrx/

и было много маппинга.

Такое ощущение, что мне нужно было сопоставить временное событие с последовательностью ключевых событий, происходящих в секунду. Но не понимаю, как я мог сопоставить их.

Что-то типа

// doing this way we could removed some code from timer$, we just need to get an event
var kps$ = timer$.concatMap(function(time) {

  var sum = keypressObservable$.takeUntil(timer$)
    .reduce(function (acc, cur) {
      return acc + cur;
    })

  console.log('sum', sum);

  return sum;
})

// this works, counts the keypresses, but only when pressing at least 1. 
kps$.subscribe(
  function (x) {
    console.log('kps next', x);
    self.keypressesReactive += x + ', ';
  });

Как заставить kps$ выдавать 0 сумм, если за секунду не было нажатий клавиш, если я использую kps$?

Обновить

Основываясь на ответе, я сделал это.

var source = Observable.fromEvent(document.body, 'keypress');

var delayedSource = source.delay(1000);


var obs = source

  .buffer(delayedSource)


  .map((clickBuffer) => {
    return clickBuffer.length;
  })

Но когда я подписываюсь на obs, я не получаю событие каждую секунду, содержащее значение 0. Когда я нажимаю несколько клавиш в секунду, я получаю количество нажатых клавиш и другое событие 0. И затем события останавливаются, пока я снова не нажму клавиши. Что мне нужно изменить, чтобы я получал событие каждую секунду?


person Dariux    schedule 02.04.2016    source источник


Ответы (1)


Я думаю, что вы могли бы использовать оператор буфера. Это позволяет буферизовать события и отправлять их через определенное время. Затем вы можете сопоставить этот список событий с его длиной.

var source = Observable.fromEvent(document.body, 'keyup');

var obs = source
     .bufferTime(1000).map((clickBuffer) => {
       return clickBuffer.length;
     });

obs.subscribe((num) => {
  // Get the number of pressed keys per second
});

См. эти ссылки:

person Thierry Templier    schedule 02.04.2016
comment
У меня не работает, по крайней мере в RxJs 5 - получаю ошибку: Ошибка: (161, 15) TS2345: Аргумент типа '() => Observable‹{}›' не может быть назначен параметру типа 'Observable‹any› '. Свойство _isScalar отсутствует в типе '() => Observable‹{}›'. - person Dariux; 03.04.2016
comment
Нашел как исправить ошибку - передал delayedSource в функцию буфера. Но все равно не получается так как я хочу - person Dariux; 03.04.2016
comment
Ты прав. Вы должны использовать оператор bufferTime. Я обновил свой ответ соответственно... - person Thierry Templier; 03.04.2016