繁体   English   中英

RxJS5 =>订阅者的onCompleted回调未触发

[英]RxJS5 => subscriber's onCompleted callback not firing

我在队列中有这两种方法。 我已经实现了某种形式的背压,其中从方法创建的可观察对象仅在用户触发回调时才通过所有可观察对象触发事件。 问题是我无法让onCompleted处理程序在主订户中触发到drain() 令我惊讶的是,onNext会为同一订户触发,那么为什么onCompleted不会触发? 我认为在takeUntil调用和繁重的$ obs.complete()之间,订户中的onCompleted处理程序将触发...

Queue.prototype.isEmpty = function (obs) {

    if (!obs) {
        // this is just a dummy observable
        // I wish Rx had Rx.Observable.dummy() alongside
        // Rx.Observable.empty(), but oh well
        obs = Rx.Observable.of('dummy');
    }

    return this.init()
        .flatMap(() => {
            return obs; // when you call obs.next(), it should fire this chain again
        })
        .flatMap(() => {
            return acquireLock(this)
                .flatMap(obj => {
                    return acquireLockRetry(this, obj)
                })
        })
        .flatMap(obj => {
            return findFirstLine(this)
                .flatMap(l => {
                    return releaseLock(this, obj.id)
                        .map(() => {
                            console.log(' => LLLL1 => ', l);
                            return l;
                        });
                });
        })
        .filter(l => {
            // filter out any lines => only fire event if there is no line

            return !l;
        })
        .map(() => {
            //  the queue is now empty
            obs.complete(); // <<<<<<<<<< note this call
            return {isEmpty: true}
        });


};


Queue.prototype.drain = function (obs, opts) {

    opts = opts || {};

    const isConnect = opts.isConnect || false;
    const delay = opts.delay || 500;

    let $obs = obs.takeUntil(this.isEmpty(obs))
        .flatMap(() => {
            return this.init();
        })
        .flatMap(() => {
            return acquireLock(this)
                .flatMap(obj => {
                    return acquireLockRetry(this, obj)
                });
        })
        .flatMap(obj => {
            return removeOneLine(this)
                .flatMap(l => {
                    return releaseLock(this, obj.id)
                        .map(() => l);
                });
        });


    process.nextTick(function(){
        obs.next('foo foo foo');
        $obs.next('bar bar bar');
        $obs.complete();
    });


    return $obs;

};

推动绝对疯狂的是,当我像上面这样调用上面的代码时,无法触发onCompleted回调:

const q = new Queue();

const obs = new Rx.Subject();

q.drain(obs).subscribe(

    function (v) {

        console.log('end result => ', colors.yellow(util.inspect(v)));

        setTimeout(function () {
            // the following call serves as the callback which will fire the observables in the methods again
            obs.next();
        }, 100);

    },
    function (e) {
        console.log('on error => ', e);
    },
    function (c) {
        // this never gets called and it is driving me f*cking crazy
        console.log(colors.red(' DRAIN on completed => '), c);
    }

);

obs.subscribe(
    function (v) {
        console.log('next item that was drained => ', v);
    },
    function (e) {
        console.log('on error => ', e);
    },
    function (c) {
        // this gets called!
        console.log(colors.red(' => obs on completed => '), c);
    }
);

当我拨打上述电话时​​,我得到的是:

next item that was drained =>  foo foo foo
next item that was drained =>  bar bar bar
 => obs on completed =>  undefined

我只得到那三行的原因是因为我这样做:

process.nextTick(function(){
    obs.next('foo foo foo');
    $obs.next('bar bar bar');
    $obs.complete();
}); 

但是为什么不显式调用$obs.complete(); 触发此回调:

 function (c) {
            // this never gets called and it is driving me f*cking crazy
            console.log(colors.red(' DRAIN on completed => '), c);
        }

好吧,我想我已经知道了,这个RxJS多么疯狂的库

最有可能做对的事情,您可能应该使用take()或takeUntil()或类似的方法

所以我这样做:

Queue.prototype.drain = function (obs, opts) {

    if (!(obs instanceof Rx.Observable)) {
        opts = obs || {};
        obs = new Rx.Subject();
    }
    else {
        opts = opts || {};
    }


    const isConnect = opts.isConnect || false;
    const delay = opts.delay || 500;

    process.nextTick(function () {
        obs.next();
    });


    let $obs = obs
        .flatMap(() => {
            return this.init();
        })
        .flatMap(() => {
            return acquireLock(this)
                .flatMap(obj => {
                    return acquireLockRetry(this, obj)
                });
        })
        .flatMap(obj => {
            return removeOneLine(this)
                .flatMap(l => {
                    return releaseLock(this, obj.id)
                        .map(() => ({data: l, cb: obs.next.bind(obs)}));
                });
        })
        //  here is the key part!
        .takeUntil(this.isEmpty(obs));


    return $obs;

};

这似乎已经解决了问题。 我有一段时间没有希望了。 如果您想进一步了解其工作原理,请在内部询问。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM