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

时间:2017-01-04 04:09:54

标签: javascript node.js rxjs5

我在队列中有这两种方法。我已经实现了某种形式的背压,其中从方法创建的observable只会在用户通过observables触发回调时触发事件。问题是我无法将主要订阅者中的onCompleted处理程序触发到add。让我感到惊讶的是,onNext会为同一个用户开火,那么为什么不能完成火灾呢?我认为在takeUntil调用和重量级的$ obs.complete()之间,订阅者中的onCompleted处理程序将触发......

drain()

什么是绝对疯狂的驱动力,就是当我打电话给上面这样的时候,我无法获得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;

};

当我打电话给上面的时候,我就明白了:

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);
    }
);

我刚刚获得这3行的原因是因为我这样做:

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();

1 个答案:

答案 0 :(得分:0)

好吧,我想我想出来了,这是一个疯狂的图书馆这个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;

};
似乎已经完成了这个伎俩。我有一段时间没有绝望了。如果您想进一步解释其工作原理,请在内部查询。