加入RX.js中的两个observable

时间:2013-07-12 20:02:42

标签: system.reactive reactive-programming reactive-extensions-js

我正在尝试基于另外两个创建新的observable。我有:

var mouseClickObservable = Rx.Observable.fromEvent(this.canvas, "click");
var mouseMoveObservable = Rx.Observable.fromEvent(this.canvas, "mousemove");
function findObject(x, y) {/* logic for finding object under cursor here. */}
var objectUnderCursor = this.mouseMoveObservable.select(function (ev) { 
    return findObject(ev.clientX, clientY);
});

我想创建objectClicked observable,它应该在用户点击对象时产生值。我可以再次调用findObject,如下所示:

var objectClicked = this.mouseClickObservable.select(function (ev) { 
    return findObject(ev.clientX, clientY);
});

但这是非常耗时的功能。

我目前使用的另一种方法是将最后一个悬停的对象存储在变量中,但我认为,应该有纯粹的功能方式来做到这一点。我试着像这样使用Observable.join:

var objectClicked = this.objectUnderCursor.join(
    mouseClickObservable,
    function (obj) { return this.objectUnderCursor },
    function (ev) { return  Rx.Observable.empty() },
    function (obj, ev) { return obj })

但它只需点击一次即可生成多个值

1 个答案:

答案 0 :(得分:0)

我没有看到您实际订阅的任何代码到您定义的任何这些可观察对象,因此很难提供一个好的答案。你真的需要在每次移动鼠标时调用findObject吗?当鼠标移动时,您是否需要提供某种悬停效果?或者您只需要知道被点击的对象,在这种情况下,您只需要在点击时调用findObject一次?

假设您只需要知道点击了什么对象,您甚至不用担心鼠标移动,只需执行以下操作:

var objectClicked = mouseClickObservable
    .select(function (ev) { return findObject(ev.clientX, ev.clientY); });

objectClicked.subscribe(function(o) { ... });

如果你确实需要知道鼠标悬停在哪个对象上,但是想要避免在点击时调用昂贵的命中测试,那么你确实需要存储中间值(无论如何你需要存储它)你的悬停效果)。您可以使用BehaviorSubject来实现此目的:

this.objectUnderCursor = new Rx.BehaviorSubject();
mouseMoveObservable
    .select(function (ev) { return findObject(ev.clientX, ev.clientY); })
    .subscribe(this.objectUnderCursor);


this.objectUnderCursor.subscribe(function (o) { do your hover effects here });
mouseClickObservable
    .selectMany(function () { return this.objectUnderCursor; })
    .subscribe(function (o) { do your click effect });