2015-05-12 16 views
7

Ich habe einen Strom randStream, die alle halbe Sekunde einen zufälligen Wert und boolStream ausgeben, der Wert von randStream in Boolean konvertiert.Reaktive Programmierung - Wert ist größer als X für N Sekunden

let randStream = Kefir.fromPoll(500,() => Math.random()) 
let boolStream = Kefir.map((rand) => rand > 0.5) 

Ich möchte true auszusenden, wenn boolStreamtrue für 5 Sekunden (in einer Reihe) emittiert. Sonst emit falsch.

Ich benutze Kefir.js Bibliothek.

Haben Sie irgendwelche Ideen? Vielen Dank.

Antwort

1

Mit den gegebenen Bedingungen, wenn Sie genaue Rate, mit der wissen randStream emittieren Zahlen, es ist ziemlich einfach, mit .slidingWindow zu erreichen:

let result = boolStream 
    .slidingWindow(10, 10) 
    .map(items => _.every(items)) 
    .skipDuplicates(); 

Wenn Sie es mit jeder Rate von Ereignissen arbeiten möchten, können Sie so etwas wie versuchen:

let result = boolStream 
    .scan(({mostRecentFalse, latestValue}, bool) => { 
    return bool ? 
     {mostRecentFalse, latestValue: true} : 
     {mostRecentFalse: Date.now(), lastValue: false} 
    }, {mostRecentFalse: Date.now()}) 
    .changes() 
    .map(({mostRecentFalse, latestValue}) => 
    latestValue && (Date.now() - mostRecentFalse > 5000)) 
    .skipDuplicates(); 
1

Entschuldigung, ich kann ES6 noch nicht schreiben, aber ... die Idee ist, wenn dein Original-Stream einmal pro halbe Sekunde Sampling ist, sind fünf Sekunden true elf Wahrheiten in einer Reihe, richtig?

// generate random numbers 
var randStream = Kefir.fromPoll(500, function() { 
    return Math.random(); 
}); 

// make into booleans 
var boolStream = randStream.map(function(rand) { 
    return rand > 0.5; 
}); 

// count trues in a row 
var trueStreakStream = boolStream.scan(function(numTrue, curr) { 
    return curr ? numTrue + 1 : 0; 
}, 0); 

// see when there's exactly 11 of them 
var elevenTruesStream = trueStreakStream.filter(function(numTrue) { 
    return numTrue == 11; 
}); 

// react 
elevenTruesStream.onValue(function(numTrue) { 
    console.log("five seconds of true!"); 
}); 

EDIT: Ich lese gerade Ihre Frage noch einmal; Wenn Sie einen Stream wollen, dass true, wenn alle Ihre letzten 5 Sekunden true waren sein wird, verwenden Sie dann map statt filter (und >= statt ==):

var lastElevenAreTrueStream = trueStreakStream.map(function(numTrue) { 
    return numTrue >= 11; 
}); 
Verwandte Themen