Rx.js fromEvent + flatMapLatest 坏了?
Rx.js fromEvent + flatMapLatest broken?
嗯,这个问题本身有点难以简单描述,所以这里有一个live example来演示一下。看来我对 Rx.js 的工作原理有些误解,否则这里的功能来自错误。
我尝试做的是一个简单的反应式渲染设置,您在屏幕上看到的内容以及发生的事件都根据 Observables 进行描述。问题是,由于某些难以辨认的原因,当代码以一种方式编写时,事件将被完全删除,但在理论上应该等效的代码上工作正常。
所以,让我们从上面示例代码中的第一个案例开始:
var dom = makeBox('one');
var clicks = Rx.Observable.fromEvent(dom, 'click');
如果您创建了一个 DOM 片段,那么您可以简单地使用 fromEvent 为它发出的任何事件获取一个 Observable。到目前为止,一切都很好。您可以单击此框并查看写入日志的一堆行。
现在,下一步是使 DOM 具有反应性,以表达它如何随时间变化。
var domStream = Rx.Observable.return(makeBox('two'));
var clicks = domStream.flatMapLatest(function(dom) {
return Rx.Observable.fromEvent(dom, 'click');
});
这将使它成为一个 Observable,在这里使用 return 来产生最简单的常量情况。您感兴趣的事件将是由 dom 的最新版本发出的事件,而这正是 flatMapLatest 运算符所做的。此变体仍然有效。
最终,目标是根据某些应用程序状态生成当前 DOM 状态。也就是说,将它从一个 Observable 映射到另一个。现在让我们使用最简单的版本,将单个常量值作为状态,然后将其映射到我们之前使用的相同固定输出:
var updates = Rx.Observable.return(1);
var domStream = updates.map(function (update) {
return makeBox('three');
});
var clicks = domStream.flatMapLatest(function(dom) {
return Rx.Observable.fromEvent(dom, 'click');
});
这应该与以前的版本没有什么不同。但是,无论您做什么,这都不会输出任何事件。
这里到底发生了什么?我是不是误解了 Rx 的一些基本概念,还是什么?我已经 运行 研究了热与冷 Observables 的一些问题,但在这个最小的情况下这似乎无关紧要。所以,我有点没主意了。谁能赐教一下?
很抱歉告诉你,这是一个 Hot vs Cold
问题。
这是一个微妙的问题,但是
之间的区别
Rx.Observable.return(makeBox('two'))
和
Rx.Observable.return(1).map(function() {return makeBox('three'); })
是不是第一个returns每次订阅都是一个常量,也就是
您最初创建的框。每次订阅 Observable
时,第二个 returns 一个 new 框,这会导致问题,因为您实际上订阅了 domStream
变量两次,您正在创建 Box 3 的两个实例,一个具有事件处理程序但未显示,另一个没有但已显示。
解决方法是您需要使用方法 2 或 您需要将第三种方法转换为热流,方法是:
domStream.replay(1).refCount()
或使用
domStream.publish()
然后在所有订阅完成后:
domStream.connect()
嗯,这个问题本身有点难以简单描述,所以这里有一个live example来演示一下。看来我对 Rx.js 的工作原理有些误解,否则这里的功能来自错误。
我尝试做的是一个简单的反应式渲染设置,您在屏幕上看到的内容以及发生的事件都根据 Observables 进行描述。问题是,由于某些难以辨认的原因,当代码以一种方式编写时,事件将被完全删除,但在理论上应该等效的代码上工作正常。
所以,让我们从上面示例代码中的第一个案例开始:
var dom = makeBox('one');
var clicks = Rx.Observable.fromEvent(dom, 'click');
如果您创建了一个 DOM 片段,那么您可以简单地使用 fromEvent 为它发出的任何事件获取一个 Observable。到目前为止,一切都很好。您可以单击此框并查看写入日志的一堆行。
现在,下一步是使 DOM 具有反应性,以表达它如何随时间变化。
var domStream = Rx.Observable.return(makeBox('two'));
var clicks = domStream.flatMapLatest(function(dom) {
return Rx.Observable.fromEvent(dom, 'click');
});
这将使它成为一个 Observable,在这里使用 return 来产生最简单的常量情况。您感兴趣的事件将是由 dom 的最新版本发出的事件,而这正是 flatMapLatest 运算符所做的。此变体仍然有效。
最终,目标是根据某些应用程序状态生成当前 DOM 状态。也就是说,将它从一个 Observable 映射到另一个。现在让我们使用最简单的版本,将单个常量值作为状态,然后将其映射到我们之前使用的相同固定输出:
var updates = Rx.Observable.return(1);
var domStream = updates.map(function (update) {
return makeBox('three');
});
var clicks = domStream.flatMapLatest(function(dom) {
return Rx.Observable.fromEvent(dom, 'click');
});
这应该与以前的版本没有什么不同。但是,无论您做什么,这都不会输出任何事件。
这里到底发生了什么?我是不是误解了 Rx 的一些基本概念,还是什么?我已经 运行 研究了热与冷 Observables 的一些问题,但在这个最小的情况下这似乎无关紧要。所以,我有点没主意了。谁能赐教一下?
很抱歉告诉你,这是一个 Hot vs Cold
问题。
这是一个微妙的问题,但是
之间的区别Rx.Observable.return(makeBox('two'))
和
Rx.Observable.return(1).map(function() {return makeBox('three'); })
是不是第一个returns每次订阅都是一个常量,也就是
您最初创建的框。每次订阅 Observable
时,第二个 returns 一个 new 框,这会导致问题,因为您实际上订阅了 domStream
变量两次,您正在创建 Box 3 的两个实例,一个具有事件处理程序但未显示,另一个没有但已显示。
解决方法是您需要使用方法 2 或 您需要将第三种方法转换为热流,方法是:
domStream.replay(1).refCount()
或使用
domStream.publish()
然后在所有订阅完成后:
domStream.connect()