创建RXJS中断计时器

时间:2017-11-19 17:20:29

标签: javascript rxjs

现在我有一个显示变量,它使用流的值进行更新。超级简单:

display$
    .distinctUntilChange()
    .subscribe((val) => this.display = val);

我还有一个"中断"消息功能将this.display更改为传入的值2秒,然后使用setTimeout将其还原。我想更改此部分以使用流。因此,每当我的中断$流中出现一个值时,它会将显示值更改为2秒,然后再返回显示的最新消息$。

我尝试绘制它:

display$    --A-----C----------->
interrupt$  ----B----D-|----|--->
final       --A-B----D------C--->

我有两个"结束"中断流上的标记尝试表示定时器启动时将其恢复为显示$。当D进入时,当前的非rx代码取消B计时器。

2 个答案:

答案 0 :(得分:1)



// mock streams
const [display$, interrupt$] = [].slice.call(document.querySelectorAll('button'))
  .map((b, i) =>
    Rx.Observable.fromEvent(b, 'click')
    .map((e, idx) => `${i === 0 ? 'DISPLAY' : 'INTERRUPT'}-${idx}`)
  )

Rx.Observable.combineLatest(
    display$,
    interrupt$.startWith(null)
    .switchMap(v => Rx.Observable.of(v)
      .merge(Rx.Observable.of(null).delay(2000))
    )
  )
  .map(([d, i]) => i || d)
  .distinctUntilChanged()
  .do(x => console.log(x))
  .subscribe()

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.js"></script>

<button>display</button>
<button>interrupt</button>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

这是一个基于将display$转换为热观察

的解决方案

console.clear() 
const Observable = Rx.Observable

const display$ = Observable.merge(
  Observable.of('A').delay(20),
  Observable.of('C').delay(70),
)

const interrupt$ = Observable.merge(
  Observable.of('B').delay(40),
  Observable.of('D').delay(80),
)

const delayed$ = interrupt$
  .delay(2000)
  .withLatestFrom(display$)
  .map(([i,d]) => d)
  .last(x => x)

const offSignal$ = interrupt$.map(x => false).publish().refCount() 
const onSignal$ = delayed$.map(x => true).startWith(true).publish().refCount() 
const displayHot$ = display$.publish()
const displayOut$ = onSignal$.flatMap(() => displayHot$.takeUntil(offSignal$))
displayHot$.connect()

const output = Observable.merge(
  displayOut$.map(x => 'display:'+x), 
  interrupt$.map(x => 'interrupt:'+x), 
  delayed$.map(x => 'delayed:'+x)
)

const start = new Date()
output.timestamp().subscribe(x => console.log(`Value: ${x.value}, elapsed: ${x.timestamp-start}`))
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.js"></script>