rxjs可观察的变化间隔

时间:2017-02-07 00:38:45

标签: javascript typescript rxjs

我有一个观察者,应该每隔X秒完成一次动作。 X的值动态变化。我一直无法绕过如何在运行时动态更改此间隔。根据我的理解,我的想法中的一个重大突破是Observables一旦被定义就无法改变,所以尝试用新的区间值重新定义Observalbe似乎不是正确的方法。

我一直在尝试使用位于https://www.learnrxjs.io/operators/transformation/switchmap.html

的代码

到目前为止,我认为switchMap至少在正确的轨道上。有人能够提供一个例子或指向我可能对我有用的资源吗?

至少,世界肯定需要更多的RxJs例子!

4 个答案:

答案 0 :(得分:9)

您可以使用Subject以及switchMapinterval动态控制期间。每当主题发出一个值时,该值可用于指定间隔的周期:



const t = Date.now();

let subject = new Rx.Subject();
subject
  .switchMap(period => Rx.Observable.interval(period))
  .do(() => console.log('some action at time T+' + (Date.now() - t)))
  .take(8)
  .subscribe();

subject.next(50);
setTimeout(() => subject.next(100), 200);
setTimeout(() => subject.next(200), 400);

<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:6)

添加一个工作示例来帮助Google员工

HTML:

<body>
  <button id="start">Start</button>
  <button id="stop">Stop</button>
  <button id="update">Update</button>
  <input id="i1" value=100></input>
</body>

JavaScript(TypeScript):

let startButton = document.getElementById('start');
let stopButton  = document.getElementById('stop');
let updateButton = document.getElementById('update');
let i1 = document.getElementById('i1');

const start$ = Rx.Observable.fromEvent(startButton, 'click');
const stop$ = Rx.Observable.fromEvent(stopButton, 'click');
const update$ = Rx.Observable.fromEvent(updateButton, 'click')

const period = () => (parseInt(i1.value));


Rx.Observable.merge(
    start$, 
    update$, 
  )
  .switchMap(() => {
    return Rx.Observable.interval(period()).takeUntil(stop$);
  })
  .subscribe(res => {
    console.log('here in the subscription:' + res);
  })

答案 2 :(得分:1)

这是我使用rxjs 6的解决方案

import { interval, from } from 'rxjs';
import { map, take, concatAll, catchError, finalize } from 'rxjs/operators';

      from([1,2,4,10])
      .pipe(
        // for each item, we create interval, and take the first element
        map(x => interval(x * 1000).pipe(take(1))),
        // concat all first elements
        concatAll(),
        // handle errors
        catchError((error) => {
          console.log('oops, something bad in pipe');
          throw error;
        }),
        // finish retry
        finalize(() => {
          console.log('stop trying');
        }),
      )
      // now subscribe and perform the actual retry
      .subscribe(val => {
        console.log('perform retry');
      });

在此示例中,我尝试在1,2,4和10秒后重新连接4次。

答案 3 :(得分:0)

这是一个基于RxJS 6的优雅解决方案:

import { interval, BehaviorSubject } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';

export class SomeComponent implements OnInit {
  private interval$: BehaviorSubject<number> = new BehaviorSubject(10000);

  ngOnInit() {
    this.interval$.pipe(
        //Assuming that the value provided by the input is in seconds
        switchMap(value => interval(value * 1000)),
        tap(() => this.doStuff())
    )
    .subscribe();
  }

  intervalChanged(value){
    console.log(value);
    this.interval$.next(value);
  }

  doStuff(){
    console.log("Hi!");
  }
}

模板:

<input (input)="intervalChanged($event.target.value)" type="number">