当手动刷新时,rxjs轮询定时器和重置计时器上的数据

时间:2017-12-12 19:56:24

标签: rxjs

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

我有一个api,我需要每5分钟轮询一次。用户还可以手动刷新数据。该数据存储在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>
&#13;
&#13;
&#13;

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

2 个答案:

答案 0 :(得分:3)

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

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分钟的计时器(你在问题中提到过。)

答案 1 :(得分:0)

在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事件相关的成功操作。