examples in the RxJS README似乎暗示我们必须订阅来源。换句话说:我们等待源发送事件。从这个意义上说,来源似乎是基于推送:来源决定何时创建新项目。
然而,这与迭代器形成了鲜明对比,严格来说,新项目只需要在需要时创建,即调用next()
时。这是pull-based
行为,也称为 lazy 生成。
例如,流可以返回所有维基百科页面的素数。这些项目仅在您提出要求时生成,因为预先生成所有项目都是一笔投资,而且可能只有2或3项可能会被阅读。
RxJS是否也有这种基于拉动的行为,以便只在您要求时生成新项目?
page on backpressure似乎表明这还不可能。
答案 0 :(得分:4)
简短的回答是否定的。
RxJS是为被动应用程序而设计的,正如您已经提到的,如果您需要基于拉取的语义,那么您应该使用Iterator
而不是Observable
。 Observables
设计是迭代器的基于推送的对应物,因此它们在算法上确实占据了不同的空间。
显然,我不能说永远不会发生,因为社区将决定这一点。但据我所知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>