Ricerca nel sito web

javascript - Contare gli eventi in un periodo di tempo e restituire la somma una volta al secondo in RxJS


È possibile contare gli eventi su un periodo di tempo e ottenere la somma una volta ogni secondo in RxJS? Ho un flusso continuo e infinito di eventi. Ogni 1 secondo vorrei ottenere il numero totale di eventi nell'ultima finestra di 5 minuti. L'idea è di usare questo per popolare un grafico in tempo reale.

So come fare questo nel modo tradizionale ma mi piacerebbe davvero capire come si fa con la programmazione reattiva.

Risposta n. 1

Ecco come lo affronterei.

Crea un observable che conta semplicemente il numero di eventi ricevuti ed emette questo come un totale progressivo (tramite scan). Crea un secondo observable che è solo il totale progressivo ritardato di 5 minuti. Crea un terzo observable che sottrae semplicemente l'observable ritardato dal primo observable. Questo restituirà il totale progressivo degli eventi che hanno meno di 5 minuti. Crea un observable finale che campiona questo terzo observable una volta al secondo.

const totalLast5Minutes = eventSource.publish(events => {
    const runningTotal = events
        .scan((e, total) => total + 1, 0)
        .startWith(0);
    const totalDelayed5Minutes = runningTotal
        .delay(5000 * 60)
        .startWith(0);
    return Rx.Observable
        .combineLatest(total, totalDelayed5Minutes, (t, td) => t - td);
});

// only sample the value once per second
Rx.Observable
    .interval(1000)
    .withLatestFrom(totalLast5Minutes, (interval, total) => total)
    .subscribe(total => console.log(`total=${total}`));

Risposta n. 2

Ecco un altro modo di farlo che penso possa essere un po' più semplice. Puoi usare windowWithTime - vedi la documentazione di ReactiveX e RxJS. Puoi creare finestre che si sovrappongono, quindi puoi avere una finestra di 5 minuti di eventi, seguita da un'altra finestra di 5 minuti di eventi che è iniziata un secondo dopo, e un'altra un secondo dopo ancora, ecc.

Se prendi il conteggio di ciascuna di queste finestre, otterrai una serie di conteggi di eventi di 5 minuti, ciascuno a un secondo di distanza. Apparirebbe qualcosa del genere:

source.windowWithTime(5 * 60000, 1000)   // create 5 minute windows, one second apart
      .flatMap(window => window.count()) // take each window and get the count once it completes (after 5 minutes)
      .subscribe(count => console.log(count));

Ho usato questo per fare esattamente quello che dici - ottenere un tasso di eventi su una finestra di tempo in un flusso continuo di eventi. Facendo sovrapporre le finestre, si genera una media mobile dell'attività sul flusso.