我有一个项目流,我想缓冲它们,直到其中一个项目符合条件。一旦满足条件,缓冲的项目应该交付给订户。
如果源可观察完成但尚未满足条件,我希望产生错误。
这可以使用RxJava中的默认运算符或Rx系列的其他语言实现吗?
答案 0 :(得分:1)
我已经使用RxJS编写了下面的示例,以便我们可以在此处运行示例。这些概念与RxJava相同。
A BufferedSubject
:
class BufferedSubject extends Rx.Subject {
constructor(predicate) {
super();
this.predicate = predicate;
this.buffer = [];
this.unbuffered = false;
}
onNext(e) {
if (this.unbuffered) {
super.onNext(e);
return;
}
if (this.predicate(e)) {
while (this.buffer.length) {
super.onNext(this.buffer.shift());
}
super.onNext(e);
this.unbuffered = true;
return;
}
this.buffer.push(e);
}
}
您可以像使用常规主题一样使用BufferedSubject
,作为某个源可观察源与您期望的缓冲可观察量之间的中介 - 您订阅主题并且主题订阅源可观察源,主题维护项目的缓冲区,直到某些条件成立。例如:
const timer = Rx.Observable.interval(5000);
const subject = new BufferedSubject((item) => item > 5);
subject.subscribe(
x => $('.list').append(`<li>${x} seconds</li>`)
);
timer.subscribe(subject);
作为一个可运行的片段(从ES6编译,抱歉):
'use strict';
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError('Cannot call a class as a function');
}
}
function _possibleConstructorReturn(self, call) {
if (!self) {
throw new ReferenceError('this hasn\'t been initialised - super() hasn\'t been called');
}
return call && (typeof call === 'object' || typeof call === 'function') ? call : self;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== 'function' && superClass !== null) {
throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass)
Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
var BufferedSubject = function (_Rx$Subject) {
_inherits(BufferedSubject, _Rx$Subject);
function BufferedSubject(predicate) {
_classCallCheck(this, BufferedSubject);
var _this = _possibleConstructorReturn(this, _Rx$Subject.call(this));
_this.predicate = predicate;
_this.buffer = [];
_this.unbuffered = false;
return _this;
}
BufferedSubject.prototype.onNext = function onNext(e) {
if (this.unbuffered) {
_Rx$Subject.prototype.onNext.call(this, e);
return;
}
if (this.predicate(e)) {
while (this.buffer.length) {
_Rx$Subject.prototype.onNext.call(this, this.buffer.shift());
}
_Rx$Subject.prototype.onNext.call(this, e);
this.unbuffered = true;
return;
}
this.buffer.push(e);
};
return BufferedSubject;
}(Rx.Subject);
var timer = Rx.Observable.interval(1000).skip(1).take(50).publish();
var subject = new BufferedSubject(function (item) {
return item > 5;
});
subject.subscribe(function (x) {
return $('.list').append('<li>' + x + ' seconds</li>');
}, function (e) {
return $('.list').append('<li>Errror ' + e + '</li>');
}, function (_) {
return $('.list').append('<li>Sequence complete</li>');
});
timer.subscribe(subject);
timer.subscribe(function (x) {
return $('.timer').text(x + ' seconds elapsed');
});
timer.connect();
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.7/rx.all.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<p>Output (<span class='timer'>-</span>):</p>
<ul class="list">
</ul>
&#13;
(也可在CodePen上找到。)
注意:我说这个实现不能正确支持背压。