在RxJS中创建一个可观察的"已完成"事件

bni*_*and 7 javascript reactive-programming rxjs

鉴于:反应式扩展拖放示例,您如何只订阅drop事件?

我修改了代码以订阅"已完成"的回调,但它没有完成.

    (function (global) {

    function main () {
        var dragTarget = document.getElementById('dragTarget');
        var $dragTarget = $(dragTarget);

        // Get the three major events
        var mouseup  = Rx.Observable.fromEvent(document, 'mouseup');
        var mousemove = Rx.Observable.fromEvent(document,    'mousemove');
        var mousedown = Rx.Observable.fromEvent(dragTarget, 'mousedown');

        var mousedrag = mousedown
            .filter(function(md){                   
                //console.log(md.offsetX + ", " + md.offsetY);
                return  md.offsetX <= 100
                        ||
                        md.offsetY <= 100;
            })
            .flatMap(function (md) {

                // calculate offsets when mouse down
                var startX = md.offsetX, startY = md.offsetY;

                // Calculate delta with mousemove until mouseup
                return mousemove.map(function (mm) {
                    mm.preventDefault();

                    return {
                        left: mm.clientX - startX,
                        top: mm.clientY - startY
                    };
                }).takeUntil(mouseup);
            });


        // Update position
        var subscription = mousedrag.subscribe(
        function (pos) {                    
            dragTarget.style.top = pos.top + 'px';
            dragTarget.style.left = pos.left + 'px';
        },
        function(errorToIgnore) {},
        function() {    alert('drop');});

    }

    main();

}(window));
Run Code Online (Sandbox Code Playgroud)

我已经读过热的可观察量,例如那些从鼠标事件中创建出来的,从未"完成".它是否正确?我怎么能在'drop'上收到回调?

cwh*_*ris 5

这样的事情应该可以解决问题.

(function (global) {

    function main () {
        var dragTarget = document.getElementById('dragTarget');

        // Get the three major events
        var mouseup = Rx.Observable.fromEvent(document, 'mouseup');
        var mousemove = Rx.Observable.fromEvent(document, 'mousemove');
        var mousedown = Rx.Observable.fromEvent(dragTarget, 'mousedown');

        var drop = mousedown
                .selectMany(
                    Rx.Observable
                        .concat(
                            [
                                mousemove.take(1).ignoreElements(),
                                mouseup.take(1)
                            ]
                        )
                );
    }

    main();

}(window));
Run Code Online (Sandbox Code Playgroud)

编辑:

如果您将一个observable视为一个产生多个值的异步函数,然后可能完成或错误,您将立即意识到只能有一个完成事件.

当您开始编写多个函数时,最外层函数仍然只完成一次,即使该函数内部包含多个函数.因此,即使"完成次数"的总数为3,最外部函数仍然只完成一次.

基本上,这意味着如果最外部函数假设每次拖动完成时返回一个值,则需要一种实际执行此操作的方法.您需要将拖动完成转换为最外层可观察的"onNext"事件.

你能做到的任何一种方式都可以满足你的需求.也许这是最外面的函数返回的唯一一种事件,或者它也可以返回拖动开始和移动,但只要它返回拖动完成,你就会得到你需要的东西(即使你必须稍后过滤它).

我上面给出的例子只是一种在最外层可观察量中返回拖拽的方法.