我们有以下流。
const recorders = imongo.listCollections('recorders')
.flatMapConcat(names => {
const recorders = names
.map(entry => entry.name)
.filter(entry => !_.contains(
['recorders.starts',
'recorders.sources',
'system.indexes',
'system.users'],
entry));
console.log(recorders);
return Rx.Observable.fromArray(recorders);
});
recorders.isEmpty()
.subscribe(
empty => {
if(empty) {
logger.warn('No recorders found.');
}
},
() => {}
);
recorders.flatMapConcat(createRecorderIntervals)
.finally(() => process.exit(0))
.subscribe(
() => {},
e => logger.error('Error while updating: %s', e, {}),
() => logger.info('Finished syncing all recorders')
);
如果流是空的,那么我们不想createRecorderIntervals
。上面的代码正在运行。但是,检查流是否为空,导致console.log
执行两次。为什么会这样?我能以某种方式解决它吗?
编辑:所以,经过重新思考后,我采取了以下方式,感谢@ Martin的回答
const recorders = imongo.listCollections('recorders')
.flatMapConcat(names => {
const recorders = names
.map(entry => entry.name)
.filter(entry => !_.contains(
['recorders.starts',
'recorders.sources',
'system.indexes',
'system.users'],
entry));
if(!recorders.length) {
logger.warn('No recorders found.');
return Rx.Observable.empty();
}
return Rx.Observable.fromArray(recorders);
})
.flatMapConcat(createRecorderIntervals)
.finally(() => scheduleNextRun())
.subscribe(
() => {},
e => logger.error('Error while updating: %s', e, {}),
() => logger.info('Finished syncing all recorders')
);
答案 0 :(得分:1)
当您在subscribe()
上调用Observable
方法时,会导致创建整个运算符链,并在您的情况下调用imongo.listCollections('recorders')
两次。
您可以在调用flatMapConcat(createRecorderIntervals)
之前插入运算符,以检查结果是否为空。我特别想到其中一个,但可能还有其他更适合您的需求:
takeWhile()
- 将谓词作为参数,并在返回onComplete
时发出false
。然后您的代码将如下所示:
const recorders = imongo.listCollections('recorders')
.flatMapConcat(names => {
...
return Rx.Observable.fromArray(recorders);
})
.takeWhile(function(result) {
// condition
})
.flatMapConcat(createRecorderIntervals)
.finally(() => process.exit(0))
.subscribe(...);
我不知道你的代码到底是做什么的,但我希望你明白这个想法。
编辑:如果您希望在整个Observable为空时收到通知,而不是多种方式:
do()
运算符和自定义Observer对象。您将编写一个自定义观察者,并在do()
之前使用.flatMapConcat(createRecorderIntervals)
运算符进行设置。此对象将计算其next
回调被调用的次数,以及前一个Observable何时完成,您可以判断是否至少有一个或根本没有结果。
创建ConnectableObservable
。这个可能与我们一开始就做的最相似。您可以使用recorders
运算符将ConnectableObservable
变为publish()
。然后,您可以订阅多个观察者,而无需触发操作员链。如果您订阅了所有Observers,请致电connect()
,它将按顺序向所有观察者发出值:
var published = recorders.publish();
published.subscribe(createObserver('SourceA'));
published.subscribe(createObserver('SourceB'));
// Connect the source
var connection = published.connect();
在您的情况下,您将创建两个Subjects
(因为它们同时充当Observable和Observer)并将其中一个链接到isEmpty()
,将第二个链接到flatMapConcat()
}。有关详细信息,请参阅文档:http://reactivex.io/documentation/operators/connect.html
我认为第一个选项对你来说实际上更容易。