RxJS:单击

时间:2017-07-07 17:07:51

标签: javascript rxjs observable

我是RxJS的新手并尝试做一个简单的演示,让你每隔一秒刷新一次数据。

我创建了一个按钮并从中创建了一个点击流。 问题开始时,我想创建一个流,每个按钮单击发出错误,并在一秒后再次发出true。

例如 - 初始状态为true,因为我们可以在开始时刷新。 一旦我点击按钮,新点值应该在点击后立即为假,因为我们无法进一步刷新。

最后一秒钟过后 - 该值应该再次为真。

我尝试创造并成功,但看起来很糟糕。 有什么想法可以做得更好更干净吗? 另一件事是我真的不知道在这里使用RxJS是否是一个好主意,因为简单的常规方法是将布尔值设置为true,然后在我点击后将其设置为false并使用setTimeout将其更改回真。

这就是我所做的:

// The stream of the button clicks.
$clicksStream
  // Change the click stream to the timed true false change.
  .switchMap(() => Observable
                    // Emit first value immediately and every 1 second after.
                    .timer(0, 1000)
                    // Map each one - 0 becomes false and others true.
                    .map(x => !!x)
                    // Take only first two items.
                    .take(2))
  // Always the start value is true.
  .startWith(true);

2 个答案:

答案 0 :(得分:0)

使用rxjs处理异步操作是一个很好的主意。反应式编程是关于什么的,rxjs擅长这样做。

你所产生的代码的美妙之处在于它是纯粹的。它并不依赖于任何外部环境。

使用setTimeout和好的'布尔改变状态当然会起作用,但代价是纯度和函数式编程。你会做命令式编程和副作用。并且代码的语义不会相同

button.addEventListener("click", function refresh(event) {
  refreshData();
  setTimeout(renderButton, 1000, true)
  renderButton(false)
})

这段代码的问题:它非常依赖于它的上下文。要使其发挥作用,您需要实施refreshDatarenderButton。他们还需要从该范围访问。

但是你的代码完全是独立的,你可以将它复制/粘贴到其他地方,它仍然有用。

另一个问题是点击处理函数负责太多事情(实际刷新数据,呈现按钮的新状态并启动超时。它完全打破单一责任原理

我希望我已经帮助您了解您所生成代码的好处。它实际上非常好,它只是习惯它的问题。

您可以使用startWithmapTo而不是hacky !!x进行简单的简化:)

$clicksStream
  // Change the click stream to the timed true false change.
  .switchMap(() => Observable
                    // just a timer of 1000ms
                    .timer(1000)
                    // when it emits we just return true
                    .mapTo(true)
                    // Take only first two items.
                    .startWith(false)
  )
  // Always the start value is true.
  .startWith(true);

答案 1 :(得分:0)

您可以使用timeoutWith运算符执行此操作。

$clickStream
  .switchMapTo(
    // Start with false
    Observable.of(false)
      // If no values are emitted for 1 second emit true
      .timeoutWith(1000, Observable.of(true))
  )
  .startWith(true);