BLE场景下相互依赖的Observables错误处理方案咨询
问题根因
- 你在
switchMap中手动订阅了内部通知流,内部错误被订阅回调捕获后没有正确传递到外层流,因此无法触发外层的重试逻辑 switchMap中混用async函数与Observable,导致返回值类型变为Promise包裹的Subscription,打乱了RxJS的错误传递链路- 之前的写法中错误传播链路被切断,只有连接层的错误能到达外层重试逻辑,通知层的错误被拦截在内部
正确实现方案
把所有操作都整合到同一个响应式流中,让错误可以完整向上传播,外层的重试可以覆盖所有环节:
import { from } from 'rxjs'; import { switchMap, tap, timeout, retry } from 'rxjs/operators'; const BLE_NOTIFICATION_TIMEOUT = 3000; const MAX_RETRY_COUNT = 5; this.ble.connect(macAddress) .pipe( tap(() => console.log('BLE连接成功')), // 连接成功后设置设备模式,把Promise转成Observable适配流操作 switchMap(() => from( this.ble.write(macAddress, ENV.CUSTOM_SERVICE, ENV.MODE_CHARACTERISTIC, mode) )), tap(() => console.log('设备模式设置成功')), // 模式设置完成后开启通知订阅 switchMap(() => this.ble.startNotification( macAddress, ENV.CUSTOM_SERVICE, ENV.VALUE_CHARACTERISTIC ).pipe( tap(() => console.log('收到通知数据')), // 通知流超时逻辑,错误会向上传递到外层 timeout(BLE_NOTIFICATION_TIMEOUT) )), // 所有环节的错误都会触发重试,重新执行整个连接+设置+订阅流程 retry(MAX_RETRY_COUNT) ) .subscribe( (data) => console.log(`incoming buffer: ${new Uint8Array(data).join(':')}`), (error) => console.log(`超过最大重试次数,最终错误: ${error}`) );
逻辑说明
- 所有异步操作都通过RxJS操作符串联,没有手动订阅,错误可以沿着流链路完整向上传递
- 不管是
connect连接失败、write设置模式失败、还是startNotification通知流抛出错误/超时,都会触发外层的retry逻辑,重新执行整个连接流程 - 取消了
switchMap内部的手动订阅和async混用,避免了类型与错误传递的问题
如果需要区分错误类型,仅对BLE相关错误重试,可以把retry(MAX_RETRY_COUNT)替换为retryWhen逻辑,自行判断错误类型后决定是否重试。
内容的提问来源于stack exchange,提问作者stephen
相关产品推荐
相关产品推荐

