可观察事件限制/仅在内存/背压中保留一个事件

时间:2016-12-02 14:22:37

标签: javascript rxjs reactive-programming observable

我订阅了每n秒发生一次事件的计时器

Observable.interval(1000) .startWith(0) .map( x => { return 'USER'; }

我还有其他可观察的结果,它产生的结果是从开始时无法获得的,需要一些时间才能解决。超时事件累积,当另一个事件最终触发时,我有大量请求。

 .zip(tokenService.token, (privilege: string, token: Token) => { 
       /*get request body*/ }
 .flatMap((body: any) => { /* perform refresh request */ }
 .map( x => { return x.json(); })
 .subscribe( json => {
       let token = json['token']'
       tokenService.setToken(token);
 });

有没有办法只保留一个来自计时器的最后一个事件,并丢弃其余的事件?

.last()对我不起作用,因为它确实只返回一个事件,但它什么也没有返回,我没有看到下一个超时事件。

也许这对我的问题不是一个好角度?我想每隔n秒刷新一次令牌,只有当我手上有有效令牌时才这样做(现在服务提供Observable<Token>

编辑:好的,我发现这被称为背压,并且有一篇关于它的文章:https://github.com/ReactiveX/RxJava/wiki/Backpressure

问题仍然存在。

1 个答案:

答案 0 :(得分:1)

您基本上希望根据Observable的当前状态重新触发事件。如果令牌有效且已经过了一段时间,则应创建新令牌,否则不会发生任何事情。

请参阅以下example on jsbin,其中提供了一些如何完成此操作的示例代码。使用按钮创建新的有效令牌。从那时起每秒都会生成一个新令牌(有效期为五秒)。通过无效按钮使令牌无效后,新令牌的生成将停止。

function createToken() {
  // Here you would do some (async) things to get a valid token.
  return Promise.resolve({ validUntil: new Date(+new Date() + 5000) });
}

function isTokenValid(token) {
  const date = new Date();
  return token.validUntil > date;
}

// Subject holds copy of latest token.
const token$ = new Rx.ReplaySubject(1);

// Defines the time interval to periodically query new tokens.
const period$ = Rx.Observable.interval(1000);

period$
  .withLatestFrom(token$, (p, token) => {
    if (isTokenValid(token)) {
      createToken()
        .then(token => token$.next(token));
    }
    return token;
  })
  .filter(token => isTokenValid(token))
  .subscribe(x => console.log(x));

// Button stream that invalidates token
const invalidateBtn$ = Rx.Observable.fromEvent(
  document.getElementById('invalidateBtn'), 'click')
  .subscribe(() => {
    token$.next({ validUntil: new Date(0) });
  });

// Button stream triggers creation of first valid token
const createBtn$ = Rx.Observable.fromEvent(
  document.getElementById('createBtn'), 'click')
  .subscribe(() => {
    createToken()
      .then((token) => token$.next(token));
  });