rxjs 轮询计时器上的数据并在手动刷新时重置计时器

byg*_*ace 3 rxjs

我在相关应用程序中使用以下库: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();
Run Code Online (Sandbox Code Playgroud)
<button onClick="manualGet()">Get Data</button>
Run Code Online (Sandbox Code Playgroud)

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

Ing*_*ürk 5

你的流需要两个组件——一个计时器和一些用户输入。所以让我们从用户输入开始。我会假设一些可以点击的按钮:

const userInput$ = Observable.fromEvent(button, 'click');
Run Code Online (Sandbox Code Playgroud)

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

userInput$.switchMap(() => Observable.timer(0, 5000));
Run Code Online (Sandbox Code Playgroud)

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

userInput$.startWith(null);
Run Code Online (Sandbox Code Playgroud)

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

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

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