响应式编程 - 值大于 X 达 N 秒
Reactive programming - value is greater than X for N seconds
我有一个流 randStream
,它每半秒发出一次随机值,boolStream
将值从 randStream
转换为布尔值。
let randStream = Kefir.fromPoll(500, () => Math.random())
let boolStream = Kefir.map((rand) => rand > 0.5)
我想在 boolStream
发出 true
5 秒(连续)时发出 true
。否则 emit
错误。
我正在使用 Kefir.js 库。
你有什么想法吗?谢谢。
抱歉,我还不会写 ES6,但是...我的想法是,如果您的原始流每半秒采样一次,那么 true
的五秒连续 11 个为真,对吧?
// 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!");
});
编辑:我刚刚又看了一遍你的问题;如果你想要一个流 true
如果你的最后 5 秒都是 true
,那么使用 map
而不是 filter
(和 >=
而不是==
):
var lastElevenAreTrueStream = trueStreakStream.map(function(numTrue) {
return numTrue >= 11;
});
在给定条件下,当您知道 randStream
发出数字的确切速率时,使用 .slidingWindow
:
很容易实现
let result = boolStream
.slidingWindow(10, 10)
.map(items => _.every(items))
.skipDuplicates();
如果您希望它适用于任何事件速率,您可以尝试类似的方法:
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();
我有一个流 randStream
,它每半秒发出一次随机值,boolStream
将值从 randStream
转换为布尔值。
let randStream = Kefir.fromPoll(500, () => Math.random())
let boolStream = Kefir.map((rand) => rand > 0.5)
我想在 boolStream
发出 true
5 秒(连续)时发出 true
。否则 emit
错误。
我正在使用 Kefir.js 库。
你有什么想法吗?谢谢。
抱歉,我还不会写 ES6,但是...我的想法是,如果您的原始流每半秒采样一次,那么 true
的五秒连续 11 个为真,对吧?
// 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!");
});
编辑:我刚刚又看了一遍你的问题;如果你想要一个流 true
如果你的最后 5 秒都是 true
,那么使用 map
而不是 filter
(和 >=
而不是==
):
var lastElevenAreTrueStream = trueStreakStream.map(function(numTrue) {
return numTrue >= 11;
});
在给定条件下,当您知道 randStream
发出数字的确切速率时,使用 .slidingWindow
:
let result = boolStream
.slidingWindow(10, 10)
.map(items => _.every(items))
.skipDuplicates();
如果您希望它适用于任何事件速率,您可以尝试类似的方法:
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();