我对 RxSwift 相对较新,但我期待在我的项目中更多地使用它,我很乐意听到一些关于我刚刚写过的运营商的反馈。
我缺少的功能是去抖缓冲区:缓冲区的行为与debounce
运算符完全相同,但它不会仅发出最新值,而是应该自上次发射以来发出所有收集的值。
在 RxJava 中,通过使用另一个observable作为“结束选择器”的缓冲区,可以轻松实现这一点:
// From: https://github.com/ReactiveX/RxJava/wiki/Backpressure
//
// we have to multicast the original bursty Observable so we can use it
// both as our source and as the source for our buffer closing selector:
Observable<Integer> burstyMulticast = bursty.publish().refCount();
// burstyDebounced will be our buffer closing selector:
Observable<Integer> burstyDebounced = burstMulticast.debounce(10, TimeUnit.MILLISECONDS);
// and this, finally, is the Observable of buffers we're interested in:
Observable<List<Integer>> burstyBuffered = burstyMulticast.buffer(burstyDebounced);
在 RxSwift 中虽然这个版本的缓冲区运算符不存在(我认为这个问题是相关的:https://github.com/ReactiveX/RxSwift/issues/590),所以我试着自己解决这个问题。
我的第一个方法是构建去抖缓冲区:
extension ObservableType {
func debouncedBuffer(_ dueTime: RxTimeInterval, scheduler: SchedulerType) -> Observable<[E]> {
var valueBuffer: [E] = []
let observable = self.do(onNext: { (value) in
valueBuffer.append(value)
}, onError: { (error) in
valueBuffer = []
}, onCompleted: {
valueBuffer = []
}, onSubscribe: {
valueBuffer = []
}, onDispose: {
valueBuffer = []
}).debounce(dueTime, scheduler: scheduler).flatMap { (value) -> Observable<[E]> in
let emitValues = valueBuffer
valueBuffer = []
return Observable<[E]>.just(emitValues)
}
return observable
}
}
我的第二种方法是构建任何关闭条件的缓冲区(如RxJava版本):
extension ObservableType {
func buffer<R>(_ selector: Observable<R>) -> Observable<[E]> {
var valueBuffer: [E] = []
return Observable.create { observer in
let selectorSubscription = selector.subscribe(onNext: { (value) in
let emitValues = valueBuffer
valueBuffer = []
observer.on(.next(emitValues))
}, onError: { (error) in
valueBuffer = []
observer.on(.error(error))
}, onCompleted: {
valueBuffer = []
observer.on(.completed)
}, onDisposed: {
valueBuffer = []
})
let subscription = self.subscribe(onNext: { (value) in
valueBuffer.append(value)
}, onError: { (error) in
observer.on(.error(error))
selectorSubscription.dispose()
}, onCompleted: {
observer.on(.completed)
selectorSubscription.dispose()
}, onDisposed: {
observer.on(.completed)
selectorSubscription.dispose()
})
return subscription
}
}
}
我已经测试了这两个运算符,它们似乎工作,也测试了处理onError,onDispose和onCompleted事件的不同组合。
但我仍然希望听到来自更有经验的人的一些反馈,如果这至少是一个没有泄漏的可接受的解决方案,并且如果我违反了任何RX合同。
我还创建了一个带有一些测试代码的pasterbin:http://pastebin.com/1iAbUPf8
答案 0 :(得分:1)
这是buffer(bufferOpenings, bufferClosingSelector)
的我的。可能需要进一步审核。
extension ObservableType {
func buffer<R>(bufferOpenings: Observable<R>, bufferClosingSelector: (R)->Observable<R>) -> Observable<[E]> {
var valueBuffer: [E]? = nil
let operatorObservable = Observable<[E]>.create({ observer in
let subject = PublishSubject<[E]>()
let closingsSub = bufferOpenings
.doOnNext({ _ in
valueBuffer = []
})
.flatMap({ opening in
return bufferClosingSelector(opening)
})
.subscribeNext({ _ in
if let vb = valueBuffer {
subject.onNext(vb)
}
valueBuffer = nil
}
)
let bufferSub = self.subscribe(
onNext: { value in
valueBuffer?.append(value)
},
onError: { error in
subject.onError(error)
},
onCompleted: {
subject.onCompleted()
},
onDisposed: {
}
)
let subjectSub = subject.subscribe(
onNext: { (value) in
observer.onNext(value)
},
onError: { (error) in
observer.onError(error)
},
onCompleted: {
observer.onCompleted()
},
onDisposed: {
}
)
let combinedDisposable = CompositeDisposable()
combinedDisposable.addDisposable(closingsSub)
combinedDisposable.addDisposable(bufferSub)
combinedDisposable.addDisposable(subjectSub)
return combinedDisposable
})
return operatorObservable
}
}