响应式编程 - 值大于 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();