使用rx.js,如何从计时器上的现有可观察序列发出memoized结果?

时间:2015-07-17 12:10:32

标签: javascript reactive-programming rxjs

我目前正在教自己使用rxjs进行反应性编程,并且我已经为自己设置了一个创建可观察流的挑战,无论如何都会向订阅者发出相同的结果。

我已经记住了HTTP" GET"的创建。给定一个特定URL的流,我试图每两秒对该流进行操作,结果是对于计时器的每个滴答,我将从原始流中提取缓存/记忆的HTTP结果

import superagent from 'superagent';
import _ from 'lodash';

// Cached GET function, returning a stream that emits the HTTP response object
var httpget = _.memoize(function(url) {
  var req = superagent.get(url);
  req = req.end.bind(req);
  return Rx.Observable.fromNodeCallback(req)();
});

// Assume this is created externally and I only have access to response$
var response$ = httpget('/ontologies/acl.ttl');

// Every two seconds, emit the memoized HTTP response
Rx.Observable.timer(0, 2000)
  .map(() => response$)
  .flatMap($ => $)
  .subscribe(response => {
    console.log('Got the response!');
  });

我确信我必须在某处调用replay(),但无论我做什么,都会每两秒启动一次新的HTTP呼叫。我如何构造它以便我可以从URL构造一个observable并让它始终向任何后续订阅者发出相同的HTTP结果?

修改
我找到了一种方法来获得我想要的结果,但我觉得我错过了一些东西,并且应该能够通过更加简化的方法重构它:

var httpget = _.memoize(function(url) {
  var subject = new Rx.ReplaySubject();
  try {
    superagent.get(url).end((err, res) => {
      if(err) {
        subject.onError(err);
      }
      else {
        subject.onNext(res);
        subject.onCompleted();
      }
    });
  }
  catch(e) {
    subject.onError(e);
  }
  return subject.asObservable();
});

2 个答案:

答案 0 :(得分:1)

您的第一个代码示例实际上更接近于执行此操作的方式

var httpget = _.memoize(function(url) {
  var req = superagent.get(url);
  return Rx.Observable.fromNodeCallback(req.end, req)();
});

但是,这不起作用,因为fromNodeCallback中似乎存在错误。至于解决这个问题,我认为你实际上是在寻找AsyncSubject而不是ReplaySubject。后者可以工作,但前者是针对这种情况而设计的(如果对您而言,并没有数组创建的开销+缓存过期的运行时检查)。

var httpget = _.memoize(function(url) {

  var subject = new Rx.AsyncSubject();
  var req = superagent.get(url);
  Rx.Observable.fromNodeCallback(req.end, req)().subscribe(subject);
  return subject.asObservable();

});

最后,虽然map感谢您正在考虑这一点,但您可以使用直接timer的{​​{1}}重载来简化您的flatMap代码:

Observable

答案 1 :(得分:0)

除非我的问题出错,否则 list1 <- as.list(list1) list2 <- as.list(list2) do.call(paste0, expand.grid(list1, list2)) #[1] "X1" "Y1" "X2" "Y2" "X3" "Y3" 会为您解决问题,它会缓存您的观察值的最后一个值。

此代码发送一次请求,然后每200 ms给出相同的缓存响应:

Observable.combineLatest