swift - 订阅返回的发布者后如何触发流程?
问题描述
我有一个返回发布者的函数。该发布者提供后台进程的结果。我只想在订阅发布者时触发后台进程,这样就不会丢失任何结果。后台进程可以多次更新其结果,因此Future
不适合使用 with 的变体。
private let passthroughSubject = PassthroughSubject<Data, Error>()
// This function will be used outside.
func fetchResults() -> AnyPublisher<Data, Error> {
return passthroughSubject
.eraseToAnyPublisher()
.somehowTriggerTheBackgroundProcess()
}
extension MyModule: MyDelegate {
func didUpdateResult(newResult: Data) {
self.passthroughSubject.send(newResult)
}
}
我尝试了什么?
未来:
Future<Data, Error> { [weak self] promise in
self?.passthroughSubject
.sink(receiveCompletion: { completion in
// My logic
}, receiveValue: { value in
// My logic
})
.store(in: &self.cancellableSet)
self?.triggerBackgroundProcess()
}.eraseToAnyPublisher()
以我想要的方式工作,但订阅者只被调用一次(逻辑)。
延期:
Deferred<AnyPublisher<Data, Error>>(createPublisher: { [weak self] in
defer {
self?.triggerBackgroundProcess()
}
return passthroughSubject.eraseToAnyPublisher()
}
调试器显示一切都是正确的:首先是return
,trigger
但订阅者不是第一次被调用。
receiveSubscription
:
passthroughSubject
.handleEvents(receiveSubscription: { [weak self] subscription in
self?.triggerBackgroundProcess()
})
.eraseToAnyPublisher()
效果与 相同Deffered
。
我想实现的目标有可能吗?或者,最好创建一个公共发布者订阅它并从后台进程接收结果。并且该fetchResults()
函数不返回任何内容?
在此先感谢您的帮助。
解决方案
在我看来,您的最后一段代码是一个完全可行的解决方案:在检测到订阅之前不要触发后台进程。例子:
let subject = PassthroughSubject<String, Never>()
var storage = Set<AnyCancellable>()
func start() {
self.subject
.handleEvents(receiveSubscription: {_ in
print("subscribed")
DispatchQueue.main.async {
self.doSomethingAsynchronous()
}
})
.sink { print("got", $0) }
.store(in: &storage)
}
func doSomethingAsynchronous() {
DispatchQueue.global(qos: .userInitiated).async {
DispatchQueue.main.async {
self.subject.send("bingo")
}
}
}
推荐阅读
- javascript - 如何使用 Vue 和 Axios 获取 JSON 数据
- sql-server - 通过在 Always on 可用性组节点上对 SQL 查询进行负载平衡来提高应用程序性能?
- .net-core - 如何在单个查询中在 Table1、Table2 和 Mapping_Table1_Table2 表中插入数据
- windows - 批量更改多个目录中mkv文件的标题
- javascript - 当带有 async fs.readdir 的递归函数完成执行时如何得到通知?
- mysql - mysql; 更新表字段的正确方法
- javascript - 找不到模块“反应”的声明文件
- c++ - 在 C++ 中初始化新分配的内存的最快方法是什么?
- pandas - 正则表达式的熊猫系列提取物
- java - java - 如何在Java中获得小时和分钟的时差/持续时间?