Combine框架下启动不影响主数据流的副作用网络请求方案咨询
虽然苹果官方文档将handleEvents归类在调试章节,但该API没有生产环境使用限制,核心设计目的就是在发布者生命周期的各个节点注入自定义副作用,你现在示例1的实现本身是完全合理且安全的,很多生产级项目都有类似用法。
如果你确实不想使用handleEvents,可以选择以下两种替代方案:
方案1:在map操作符中触发独立请求
该方案和handleEvents效果完全一致,主管道不会等待第二个高延迟请求的结果,拿到第一个请求的返回后会立刻向下游传递数据:
cancellable = URLSession.shared.dataTaskPublisher(for: .init(string: "http://httpbin.org/delay/1")!) .map { responseData in // 触发独立的高延迟请求,cancellable2存储在对应生命周期作用域即可 cancellable2 = URLSession.shared.dataTaskPublisher(for: .init(string: "http://httpbin.org/delay/10")!) .sink(receiveCompletion: { completion in print(completion) }, receiveValue: { value in print(value) }) // 原样返回第一个请求的结果,不影响主数据流 return responseData } .sink { completion in print(completion) } receiveValue: { value in print(value) }
方案2:响应式链内管理副作用(不阻塞数据下发)
如果你希望将第二个请求也纳入主响应式链的管理范围,可以用flatMap配合Just和ignoreOutput实现,主数据流会立刻收到第一个请求的返回值,仅完成事件会等待第二个请求结束后触发,如果你不关心主管道的完成时机可以选择该方案:
cancellable = URLSession.shared.dataTaskPublisher(for: .init(string: "http://httpbin.org/delay/1")!) .flatMap { responseData in // 合并两个发布者:立刻下发原数据的Just、忽略输出的高延迟请求 return Publishers.Merge( Just(responseData).setFailureType(to: URLError.self), URLSession.shared.dataTaskPublisher(for: .init(string: "http://httpbin.org/delay/10")!) .ignoreOutput() ) } .sink { completion in print(completion) } receiveValue: { value in print(value) }
注意事项
无论选择哪种方案,第二个请求对应的cancellable2都需要存储在和主cancellable相同的生命周期作用域中,避免请求还未执行完成就被提前释放导致中断。
内容的提问来源于stack exchange,提问作者Blazej SLEBODA
相关产品推荐
相关产品推荐

