RxJS可以以拉动方式使用吗?

时间:2015-11-11 22:47:47

标签: stream reactive-programming rxjs

examples in the RxJS README似乎暗示我们必须订阅来源。换句话说:我们等待源发送事件。从这个意义上说,来源似乎是基于推送:来源决定何时创建新项目。

然而,这与迭代器形成了鲜明对比,严格来说,新项目只需要在需要时创建,即调用next()时。这是pull-based行为,也称为 lazy 生成。

例如,流可以返回所有维基百科页面的素数。这些项目仅在您提出要求时生成,因为预先生成所有项目都是一笔投资,而且可能只有2或3项可能会被阅读。

RxJS是否也有这种基于拉动的行为,以便只在您要求时生成新项目?

page on backpressure似乎表明这还不可能。

2 个答案:

答案 0 :(得分:4)

简短的回答是否定的。

RxJS是为被动应用程序而设计的,正如您已经提到的,如果您需要基于拉取的语义,那么您应该使用Iterator而不是ObservableObservables 设计是迭代器的基于推送的对应物,因此它们在算法上确实占据了不同的空间。

显然,我不能说永远不会发生,因为社区将决定这一点。但据我所知1)这种情况的语义并不是那么好2)这与对数据做出反应

的想法背道而驰。

可以找到一个非常好的概要here。它适用于Rx.Net,但概念同样适用于RxJS。

答案 1 :(得分:1)

您引用的页面中的

Controlled observable可以将push observable更改为pull。

var controlled = source.controlled();

// this callback will only be invoked after controlled.request()
controlled.subscribe(n => {
  log("controlled: " + n);
  // do some work, then signal for next value
  setTimeout(() => controlled.request(1), 2500);
});

controlled.request(1);

真正的同步迭代器是不可能的,因为它会在源不发光时阻塞。

在下面的代码段中,受控订阅者在发出信号时只获取一个项目,并且不会跳过任何值。

var output = document.getElementById("output");
var log = function(str) {
  output.value += "\n" + str;
  output.scrollTop = output.scrollHeight;
};

var source = Rx.Observable.timer(0, 1000);
source.subscribe(n => log("source: " + n));

var controlled = source.controlled();
// this callback will only be invoked after controlled.request()
controlled.subscribe(n => {
  log("controlled: " + n);
  // do some work, then signal for next value
  setTimeout(() => controlled.request(1), 2500);
});
controlled.request(1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/2.5.2/rx.all.js"></script>

<body>
  <textarea id="output" style="width:150px; height: 150px"></textarea>
</body>