使用 RxJS 事件流进行简单的序列管理

Using RxJS event streams for simple sequence management

我正在尝试学习如何在事件流中思考,并且我正在尝试通过在一些人为设计的场景中对其进行测试来全面了解它。我坚持以下方案:

假设我有两个按钮,我们称它们为 ABA 可以随时点击。 B 也可以被点击,但前提是 A 之前被点击过。换句话说,B 永远不能连续点击两次。这是相应的弹珠图(其中 x 表示事件被忽略):

clickA$ --------o--------o-------->
                |        |
clickB$ --o--o--|--o--o--|--o--o-->
          x  x  |  |  x  |  |  x
logA$   --------o--|-----o--|----->
                   |        |       
logB$   -----------o--------o----->

标准方法是将状态存储在标志中并使用 if/else 控制块做出决策,如下所示:

var a = document.getElementById('a');
var b = document.getElementById('b');
var flag = false;

a.attachEventListener('click', function(e){
  flag = true;
  console.log("A");
});
b.attachEventListener('click', function(e){
  if (flag) {
    flag = false;
    console.log("B");
  }
});

我觉得应该有一种干净、简洁的方法来做到这一点,而无需标志或一些超级混乱的事件流合并,但它正在逃避我。 RxJS 中是否有 someMethod() 以便我们可以执行以下操作以获得所需的效果?

var a = document.getElementById('a');
var b = document.getElementById('b');
var a$ = Rx.Observable.fromEvent(a, "click").map(e => "A")
var b$ = Rx.Observable.fromEvent(b, "click").map(e => "B")
           .someMethod(a$)
a$.subscribe(x => console.log(x))
b$.subscribe(x => console.log(x))

我假设 logB$ 是一个热源,就像 clickA$ 一样。

看起来像 logA$ = clickA$.

对于logB$

logB$ = clickA$.flatMapLatest(function (clickA){
          return clickB$.take(1);
        });

flatMapLatest 允许您从 clickA$ 中获取一个值,并将其关联到一个流,此处为 clickB$.take(1)。因此,flatMapLatest 将从该流发出值,直到它完成,它会在从 clickB$ 发出第一个发出的值之后完成(因为 take(1))。当来自 clickA$ 的新值到达时,取消订阅从先前值派生的先前可观察值,并订阅从新值派生的可观察值。这给了你预期的行为。

文档链接: