我有一些使用RxSwift构建的代码,我正在尝试将其转换为使用Apple的合并框架。
一种非常常见的模式是将Observable.create
用于单次可观测(通常是网络请求)。就像这样:
func loadWidgets() -> Observable<[Widget]> {
return Observable.create { observer in
// start the request when someone subscribes
let loadTask = WidgetLoader.request("allWidgets", completion: { widgets in
// publish result on success
observer.onNext(widgets)
observer.onComplete()
}, error: { error in
// publish error on failure
observer.onError()
})
// allow cancellation
return Disposable {
loadTask.cancel()
}
}
}
我试着把它Map到合并上,但我还没能弄清楚。我所能得到的最接近的是使用Future来做这样的事情:
func loadWidgets() -> AnyPublisher<[Widget], Error> {
return Future<[Widget], Error> { resolve in
// start the request when someone subscribes
let loadTask = WidgetLoader.request("allWidgets", completion: { widgets in
// publish result on success
resolve(.success(widgets))
}, error: { error in
// publish error on failure
resolve(.failure(error))
})
// allow cancellation ???
}
}
正如你所看到的,它做了大部分,但没有取消的能力。其次,future不允许有多个结果。
有没有什么方法可以像Rx Observable.create
模式一样,允许取消和可选的多个结果?
5条答案
按热度按时间enyaitl31#
我想我找到了一种在
Combine
中使用PassthroughSubject
来模拟Observable.create
的方法。下面是我做的助手:下面是它在使用中的样子:
93ze6v8z2#
据我所知,在Xcode 11 beta 3中已经放弃了对使用闭包初始化
AnyPublisher
的支持。在这种情况下,这将是Rx的Observable.create
的相应解决方案,但现在我相信,如果您只需要传播单个值,Future
是一个后藤解决方案。在其他情况下,我会返回一个PassthroughSubject
并以这种方式传播多个值,但它不允许您在观察开始时启动一个任务,我相信与Observable.create
相比,它远非理想。在取消方面,它没有类似于
Disposable
的isDisposed
属性,因此无法直接检查它的状态并停止执行自己的任务。我现在能想到的唯一方法是观察cancel
事件,但它肯定没有Disposable
那么舒服。此外,我假设cancel
实际上可能会停止来自URLSession
的网络请求等任务,这是基于以下文档:https://developer.apple.com/documentation/combine/cancellableivqmmu1c3#
在闭包外部添加isCancelled操作,并在future的闭包中检查它。isCancelled可以使用handleEvent()操作符进行切换。
在应用程序中的某个地方,您可以执行此操作以取消活动
也检查此article
kb5ga3dv4#
感谢ccwasden提供的灵感。这使用纯合并实现复制了Observable.create语义,没有任何多余的实体。
AnyPublisher.create()Swift 5.6扩展
用法
tuwxkamq5#
下面是一个解决方案,它可以用公认的解决方案解决问题: