用RxSwift实现去抖动缓冲区,这是正确的吗?

用RxSwift实现去抖动缓冲区,这是正确的吗?,swift,rx-swift,reactivex,Swift,Rx Swift,Reactivex,我对RxSwift比较陌生,但我期待在我的项目中更多地使用它,我希望听到一些关于我刚刚写的操作符的反馈 我缺少的功能是一个去Bounce缓冲区:一个行为与去Bounce操作符完全相同的缓冲区,但它不只是发出最新的值,而是应该发出自上次发出以来收集的所有值 在RxJava中,通过使用一个缓冲区和另一个可观察对象作为“关闭选择器”,很容易实现这一点: //来自:https://github.com/ReactiveX/RxJava/wiki/Backpressure // //我们必须多播原始的bu

我对RxSwift比较陌生,但我期待在我的项目中更多地使用它,我希望听到一些关于我刚刚写的操作符的反馈

我缺少的功能是一个去Bounce缓冲区:一个行为与
去Bounce
操作符完全相同的缓冲区,但它不只是发出最新的值,而是应该发出自上次发出以来收集的所有值

RxJava中,通过使用一个缓冲区和另一个可观察对象作为“关闭选择器”,很容易实现这一点:

//来自:https://github.com/ReactiveX/RxJava/wiki/Backpressure
//
//我们必须多播原始的bursty Observable,以便使用它
//作为源和缓冲区关闭选择器的源:
可观测的burstyMulticast=bursty.publish().refCount();
//burstyDebounced将是我们的缓冲区关闭选择器:
可观测burstyDebounced=burstMulticast.debounce(10,时间单位毫秒);
//最后,这是我们感兴趣的缓冲区的可观察性:
可观测burstyBuffered=burstyMulticast.buffer(burstyDebounced);
RxSwift中,虽然缓冲区操作符的这个版本不存在(我认为这个问题与:)有关,所以我尝试自己解决这个问题


我的第一个方法就是构建去抖动缓冲区:

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
    }
}
扩展类型{
func debouncedBuffer(uTime:RxTimeInterval,scheduler:SchedulerType)->可观察{
var valueBuffer:[E]=[]
让observable=self.do(onNext:{(value)in
valueBuffer.append(值)
},onError:{(错误)在
valueBuffer=[]
},未完成:{
valueBuffer=[]
},已订阅:{
valueBuffer=[]
},onDispose:{
valueBuffer=[]
}).debounce(dueTime,scheduler:scheduler).flatMap{(值)->在
让emitValues=valueBuffer
valueBuffer=[]
返回可观察值。仅(发射值)
}
可观测回波
}
}

我的第二种方法是构建缓冲区,该缓冲区可以满足任何关闭条件(如RxJava版本):

扩展类型{
func缓冲区(u选择器:可观察)->可观察{
var valueBuffer:[E]=[]
返回可观察的。在中创建{observer
让selectorSubscription=selector.subscribe(onNext:{(value)in)
让emitValues=valueBuffer
valueBuffer=[]
观察者打开(.next(emit值))
},onError:{(错误)在
valueBuffer=[]
观察者打开(.error(error))
},未完成:{
valueBuffer=[]
观察员。在(.completed)
},onDisposed:{
valueBuffer=[]
})
让subscription=self.subscription(onNext:{(value)in
valueBuffer.append(值)
},onError:{(错误)在
观察者打开(.error(error))
selectorSubscription.dispose()
},未完成:{
观察员。在(.completed)
selectorSubscription.dispose()
},onDisposed:{
观察员。在(.completed)
selectorSubscription.dispose()
})
退订
}
}
}

我已经测试了这两个操作符,它们似乎很有效,还测试了如何处理OneError、onDispose和onCompleted事件的不同组合

但如果这至少是一个无泄漏的可接受解决方案,并且我违反了任何RX合同,我仍然希望听到更有经验的人的反馈


我还用一些测试代码创建了一个pasterbin:

这是我的
缓冲区(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
    }

}
扩展类型{
func buffer(bufferOpenings:Observable,bufferClosingSelector:(R)->Observable)->Observable{
var valueBuffer:[E]?=nil
让operatorObservable=Observable.create({Observable in
let subject=PublishSubject()
设closingsub=bufferopens
doOnNext先生({uuuu}in
valueBuffer=[]
})
.flatMap({在中打开
返回缓冲区关闭选择器(打开)
})
.subscribeNext({uu}in
如果让vb=valueBuffer{
subject.onNext(vb)
}
valueBuffer=nil
}
)
让bufferSub=self.subscribe(
onNext:{中的值
valueBuffer?.append(值)
},
onError:{中有错误
subject.onError(错误)
},
未完成:{
subject.onCompleted()
},
onDisposed:{
}
)
让subjectSub=subject.subscribe(
onNext:{(值)在
observer.onNext(值)
},
OneError:{(错误)在中
observer.onError(错误)
},
未完成:{
observer.onCompleted()
},
onDisposed:{
}
)
让combinedDisposable=CompositeDisposable()
组合可处置。添加可处置(closingsSub)
combinedDisposable.addDisposable(bufferSub)
combinedDisposable.addDisposable(subjectSub)
返回组合显示
})
返回运算符可观测
}
}

我建议您在上提出公关建议,并查看。谢谢,slack频道是个好主意,我会考虑创建公关。
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
        }
    }
}
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
    }

}