这是一个开放式问题,可以有很多答案,但我发现自己在很多情况下都无法做到。有很多方法可以解决问题,但最近,我正在简化一些具有级联故障转移的设备连接代码,我想确定我最后一次扫描设备的尝试是否产生了任何结果。
为此,我想创建一个 observable,如果它在没有看到任何结果的情况下被处置,它只会发出“无扫描结果”事件,反之,如果它没有发出任何结果。
为了简洁起见,我已经从我的代码中删除了其他细节,但本质上是:
func connect(scanDuration: TimeInterval) -> Observable<ConnectionEvent> {
let scan = scan(for: scanDuration).share(replay: 1)
let connection: Observable<ConnectionEvent> =
Observable.concat(Observable.from(restorables ?? []),
connectedPeripherals(),
scan)
.flatMapLatest { [retainedSelf = self] in retainedSelf.connect(to: $0) }
let scanDetector = scan
.toArray() // <-- sum all results as an array for final count
.asObservable()
.flatMap { results -> Observable<ConnectionEvent> in
results.isEmpty // if no scan results
? Observable.just(.noDevicesAvailable) // emit event
: Observable.never() } // else, got results, no action needed
// fold source and stream detector into common observable
return Observable.from([
connection
.filter { $0.isConnected }
.flatMapLatest { [retained = self] event -> Observable<ConnectionEvent> in
retained.didDisconnect(peripheral: event.connectedPeripheral!.peripheral)
.startWith(event) },
scanDetector])
.switchLatest()
}
作为一个反驳点,我在输入此内容时意识到,还有一种更简单的方法可以满足我的需求,那就是添加一个发出 observable 的最终错误到我的 concat 中,它会故障转移,直到它遇到最后的错误情况,所以我不需要后面的错误检测流。
Observable.concat(Observable.from(restorables ?? []),
connectedPeripherals(),
scan,
hardFailureEmitNoScanResults())
也就是说,在很多情况下,我们可能想要监听和过滤下游,而 concat 技术不可用。