reactive-programming - RxSwift 如何拆分进度和结果 observables?
问题描述
我需要根据String
输入进行长时间的异步计算并返回一个大Data
实例。我使用Single
trait 来实现这一点:
func calculateData(from: String) -> Single<Data>
这个例子很简单并且有效。但我还需要跟踪进度——一个介于 0 和 1 之间的数字。我正在做这样的事情:
func calculateData(from: String) -> Observable<(Float, Data?)>
我得到以下序列:
next: (0, nil)
next: (0.25, nil)
next: (0.5, nil)
next: (0.75, nil)
next: (1, result data)
complete
我检查进度和数据以了解我是否有结果,它有效,但我觉得这里有一些强烈的气味。我想分开流:Observable
有进展和Single
结果。我知道我可以返回一个包含两个可观察对象的元组或结构,但我也不喜欢这样。
我怎样才能做到这一点?是否可以?
解决方案
你有什么很好,虽然我会命名元组中的元素
func calculateData(from: String) -> Observable<(percent: Float, data: Data?)>
let result = calculateData(from: myString)
.share()
result
.map { $0.percent }
.subscribe(onNext: { print("percent complete:", $0) }
.disposed(by: disposeBag)
result
.compactMap { $0.data }
.subscribe(onNext: { print("completed data:", $0) }
.disposed(by: disposeBag)
另一种选择是使用一个返回完成百分比或数据的枚举:
enum Progress {
case incomplete(Float)
case complete(Data)
}
func calculateData(from: String) -> Observable<Progress>
但是,这样做会使将 Observable 分成两个流变得更加困难。为此,您必须像这样扩展 Progress:
extension Progress {
var percent: Float {
switch self {
case .incomplete(let percent):
return percent
case .complete:
return 1
}
}
var data: Data? {
switch self {
case .incomplete:
return nil
case .complete(let data):
return data
}
}
}
如您所见,执行上述操作实质上会将枚举转换为您已经在使用的元组。不过,这样做的好处是您获得了编译时保证,即如果 Data 发出,则进度将为 1。
如果您想要两全其美,请使用结构:
struct Progress {
let percent: Float
let data: Data?
init(percent: Float) {
guard 0 <= percent && percent < 1 else { fatalError() }
self.percent = percent
self.data = nil
}
init(data: Data) {
self.percent = 1
self.data = data
}
}
func calculateData(from: String) -> Observable<Progress>
以上提供了枚举的编译时间保证以及使用元组获得的拆分的便利性。它还提供了运行时保证进度将为 0...1,如果为 1,则数据将存在。
推荐阅读
- github - 我需要输入什么代码才能使 expo 项目功能?
- visual-studio - 如何在 F# 中启用 WinForms 或 WPF 项目?
- sqlite - SQLite.net 数据库与 Xamarin.Forms 应用程序
- scala - 如何在异常时停止 Actor 重新加载
- c# - 在c#中运行更新查询后数据库没有变化
- python - 检查某个数字序列是否出现在数组中。我的想法有什么问题?
- c# - 在函数调用 Visual Studio 键盘快捷键中包装变量
- javascript - 通过 WKWebView 使用 Javascript、AngularJS 在设备上保存数据以自动填充表单
- wordpress - 在 Wordpress 的一般部分中添加字段
- sql-server - TFS 2015 - 在 SQL Server 中跟踪“正在做和完成”子列