我在队列中有这两种方法。我已经实现了某种形式的背压,其中从方法创建的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();
答案 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;
};
似乎已经完成了这个伎俩。我有一段时间没有绝望了。如果您想进一步解释其工作原理,请在内部查询。