根据先前的值转换Observable

时间:2016-04-16 10:36:09

标签: rxjs

  • 我有20种不同类型的活动。
  • 如果在最后10秒内发出类似类型的事件,我想为每个事件设置一个布尔值。
  • 这应该是现场直播,我不想将事件延迟10秒。
  • 事件流是连续的,不会结束

这可以用RxJs完成吗?

更新:以下是我的活动流的JsBin演示(请查看评论)http://jsbin.com/jepesu/1/edit?js,console,output

1 个答案:

答案 0 :(得分:0)

我找到了解决问题的方法。事件看起来像这样:

{
  id: 0,            // unique
  title: 'xxx',
  sound: 'p0',      // One of 'p0', 'p1', 'p2'
  playSound: false, // If the sound should be played
}

只有在最近5秒钟内没有播放相同类型的声音时,才会播放声音。 playSound是我要切换的布尔值。为此,我需要一个辅助函数:throttleMap

/**
 * Executes a map function on the first element in the window, returns the rest as is
 * In other words: Executes mapFunction on all elements the Rx.throttle() function would
 * emit, emits all other elements unchanged
 */
Rx.Observable.prototype.throttleMap = function (windowDuration, mapFunction, scheduler) {
    Rx.Scheduler.isScheduler(scheduler) || (scheduler = Rx.Scheduler.default);
    var duration = +windowDuration || 0;
    if (duration <= 0) { throw new RangeError('windowDuration cannot be less or equal zero.'); }
    var source = this;
    return new Rx.AnonymousObservable(function (o) {
      var lastOnNext = 0;
      return source.subscribe(
        function (x) {
          var now = scheduler.now();
          if (lastOnNext === 0 || now - lastOnNext >= duration) {
            lastOnNext = now;
            o.onNext(mapFunction(x));
          }
          else {
            o.onNext(x);
          }
        },function (e) { o.onError(e); }, function () { o.onCompleted(); }
      );
    }, source);
  };

现在的解决方案:

const groupedSoundStream = singleNotificationStream
  .groupBy(
    (x) => x.sound,
    (x) => x
  )
  .flatMap((x) => {
    return x.throttleMap(5000, (x) => {
      x.playSound = true
      return x
    })
  })

 groupedSoundStream
   .subscribe((x) => console.log(secSinceStart()+'s', x))

一些示例输出:

0.3s { id: 0,  title: 'M#0',  sound: 'p2', playSound: true  }
0.6s { id: 1,  title: 'M#1',  sound: 'p1', playSound: true  }
0.9s { id: 2,  title: 'M#2',  sound: 'p1', playSound: false }
1.2s { id: 3,  title: 'M#3',  sound: 'p0', playSound: true  }
1.5s { id: 4,  title: 'M#4',  sound: 'p2', playSound: false }
1.8s { id: 5,  title: 'M#5',  sound: 'p0', playSound: false }
2.1s { id: 6,  title: 'M#6',  sound: 'p1', playSound: false }
2.4s { id: 7,  title: 'M#7',  sound: 'p2', playSound: false }
2.7s { id: 8,  title: 'M#8',  sound: 'p2', playSound: false }
3.1s { id: 9,  title: 'M#9',  sound: 'p1', playSound: false }
3.4s { id: 10, title: 'M#10', sound: 'p1', playSound: false }
3.7s { id: 11, title: 'M#11', sound: 'p1', playSound: false }
4s   { id: 12, title: 'M#12', sound: 'p2', playSound: false }
4.3s { id: 13, title: 'M#13', sound: 'p0', playSound: false }
4.6s { id: 14, title: 'M#14', sound: 'p2', playSound: false }
4.9s { id: 15, title: 'M#15', sound: 'p1', playSound: false }
5.2s { id: 16, title: 'M#16', sound: 'p2', playSound: false }
5.5s { id: 17, title: 'M#17', sound: 'p2', playSound: true  }
5.8s { id: 18, title: 'M#18', sound: 'p0', playSound: false }
6.1s { id: 19, title: 'M#19', sound: 'p2', playSound: false }
6.4s { id: 20, title: 'M#20', sound: 'p1', playSound: true  }
6.7s { id: 21, title: 'M#21', sound: 'p2', playSound: false }
7s   { id: 22, title: 'M#22', sound: 'p1', playSound: false }