【问题标题】:Join two observables in RX.js在 RXjs 中加入两个 observables
【发布时间】:2013-07-12 20:02:42
【问题描述】:

我正在尝试基于另外两个创建新的 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 })

但它一键生成多个值

【问题讨论】:

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


    【解决方案1】:

    我没有看到您实际订阅您定义的任何这些可观察对象的任何代码,因此很难提供一个好的答案。你真的需要在每次鼠标移动时调用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 });
    

    【讨论】:

    • 是的,我需要知道鼠标悬停在什么地方,您的最后一个解决方案非常有帮助,但是 .selectMany(function () { return this.objectUnderCursor; }) 创建的 observable 在单击后鼠标移动时将继续产生值。我将其更改为.selectMany(function () { return this.objectUnderCursor.first(); }),它运行良好。非常感谢!
    猜你喜欢
    • 2017-09-22
    • 1970-01-01
    • 2017-10-15
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 2017-01-12
    • 2018-08-24
    相关资源
    最近更新 更多