【问题标题】:rxjs poll for data on timer and reset timerwhen manually refreshedrxjs 轮询计时器上的数据并在手动刷新时重置计时器
【发布时间】:2017-12-13 05:42:49
【问题描述】:

我在相关应用程序中使用以下库:Angular 4.x、ngrx 4.x、rxjs 5.4.x

我有一个需要每 5 分钟轮询一次的 api。用户还可以手动刷新数据。该数据存储在 ngrx 存储中。我正在使用 ngrx 效果,因此通过调度“FETCH”类型的操作来检索数据。

我想设置一个 rxjs 流,它将“FETCH”操作分派到 ngrx 存储。这将是一个 5 分钟的滑动计时器,当用户手动更新商店时会重置。订阅时,流最初应该发出一个值。

我不确定如何重置计时器。在普通的 javascript 中,我会执行以下操作:

console.clear();
let timer;
let counter = 0;

function fetch() {
  console.log('fetch', counter++);
  poll();
}

function poll() {
  if (timer != null) {
    window.clearTimeout(timer);
  }
  timer = window.setTimeout(() => {
    console.log('poll');
    fetch();
  }, 5000);
}

function manualGet() {
  console.log('manual');
  fetch();
}

fetch();
<button onClick="manualGet()">Get Data</button>

问题:当另一个流再次像示例一样发射时,如何在重置的间隔上发射?

【问题讨论】:

    标签: rxjs


    【解决方案1】:

    您希望流中有两个组件——一个计时器和一些用户输入。所以让我们从用户输入开始。我假设一些可以点击的按钮:

    const userInput$ = Observable.fromEvent(button, 'click');
    

    现在我们要启动一个计时器,它会在每次userInput$ 发出时重置。我们可以使用

    userInput$.switchMap(() => Observable.timer(0, 5000));
    

    但是,我们还希望用户无需先单击按钮即可启动此流。但这也不是问题:

    userInput$.startWith(null);
    

    现在我们把它们放在一起:

    Observable.fromEvent(button, 'click')
        .startWith(null)
        .switchMap(() => Observable.timer(0, 5000))
        .subscribe(() => dispatchFetch());
    

    请注意,我正在按照您的示例使用 5 秒计时器,而不是 5 分钟计时器(您在问题中提到。)

    【讨论】:

      【解决方案2】:

      用vanilla JS写出来后,我意识到计时器的来源应该是数据。我正在努力弄清楚来源是什么。显然它不可能是计时器,因为我需要重置它。

      我愿意接受更好的选择,但我是这样解决的:

      console.clear();
      let counter = 0;
      const data = new Rx.BehaviorSubject(null);
      
      function fetch() {
        data.next(counter++);
      }
      
      function manualGet() {
        console.log('manual');
        fetch();
      }
      
      // setup poll
      data.switchMap(() => Rx.Observable.timer(5000))
        .subscribe(() => { 
          console.log('poll');
          fetch();
        });
      
      // subscribe to the data
      data.filter(x => x != null).
        subscribe(x => { console.log('data', x); });
      
      // do the first fetch
      fetch();
      <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.5/Rx.min.js"></script>
      <button onClick="manualGet()">Get Data</button>

      使用 ngrx 我正在监听与 fetch 事件相关的成功操作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-19
        • 1970-01-01
        • 1970-01-01
        • 2021-11-18
        • 1970-01-01
        相关资源
        最近更新 更多