RxSwift:链接几个动作
RxSwift: chaining several actions
假设我们有一个 AnObject 实例数组,需要执行以下操作序列:
- 通过单独调用将对象发送到后端
- 步骤 1 完成后 将此数组批量存储到 DB
- 步骤 2 完成后 对每个项目进行额外处理
并且我们希望仅在执行所有这些步骤(或出现错误)后才接收信号。通过 RxSwift 实现此目的的正确方法是什么?实际上可行吗?
请在下面找到我的原型函数。不幸的是,我没有想出一个有效的链接代码示例,所以没有什么可以演示的。
func makeAPIRequest(object: AnObject) -> Observable<Void> {
...
}
func storeData(data: [AnObject]) -> Observable<Void> {
...
}
func additionalProcessing(object: AnObject) -> Observable<Void> {
...
}
func submitData()
{
let data: [AnObject] = ...;
let apiOperations = data.map{ makeAPIRequest([=10=]) };
let storageOperation = storeData(data);
let processingOperations = data.map{ additionalProcessing([=10=]) };
... // some code to chain steps 1-3
.subscribe { (event) -> Void in
// should be called when operations from step 3 finished
}.addDisposableTo(disposeBag);
}
让我们假设 makeAPIRequest
和 additionalProcessing
return 和 Observable<SomeNotVoidType>
和 storeData
都采用数组作为其参数并且 return一个 Observable<Array>
。
这样,您可以执行以下操作:
首先,创建一个 Observables
数组,表示将单个对象发送到后端。然后使用 toObservable
方法,因此生成的信号可以稍后进行转换:
let apiOperations = data.map{ makeAPIRequest([=20=]) }.toObservable()
然后使用 merge
运算符,这将生成 Observable
,仅当所有 API 调用完成时才完成。您还可以使用 toArray
运算符,它将 API 调用结果放入一个数组中:
let resultsArray = apiOperations.merge().toArray()
这会给你一个 Observable<Array<ApiResult>>
,它会在所有 API 操作成功完成时发送一个 Next
事件。现在您可以将结果存储在数据库中:
let storedResults = resultsArray.flatMap { storeDatabase([=10=]) }
然后您又想为每个数组元素制作 Observables
,因此它们将代表额外的处理。请注意,您需要使用 flatMap
和 flatMapLates
,否则您最终会得到像 Observable<Observable<SomeType>>
.
这样的嵌套可观察对象
let additionalProcessingResults = storedResults.flatMap {
return [=11=].map(additionalProcessing).toObservable()
}.flatMapLatest { return [=11=] }
然后,您可以订阅附加处理的成功完成(或者您可以对其单独的结果做一些事情):
additionalProcessingResults.subscribe { (event) -> Void in
// should be called when operations from step 3 finished
}.addDisposableTo(disposeBag);
请注意,您不需要所有中间变量,我只是让它们描述所有步骤。
假设我们有一个 AnObject 实例数组,需要执行以下操作序列:
- 通过单独调用将对象发送到后端
- 步骤 1 完成后 将此数组批量存储到 DB
- 步骤 2 完成后 对每个项目进行额外处理
并且我们希望仅在执行所有这些步骤(或出现错误)后才接收信号。通过 RxSwift 实现此目的的正确方法是什么?实际上可行吗?
请在下面找到我的原型函数。不幸的是,我没有想出一个有效的链接代码示例,所以没有什么可以演示的。
func makeAPIRequest(object: AnObject) -> Observable<Void> {
...
}
func storeData(data: [AnObject]) -> Observable<Void> {
...
}
func additionalProcessing(object: AnObject) -> Observable<Void> {
...
}
func submitData()
{
let data: [AnObject] = ...;
let apiOperations = data.map{ makeAPIRequest([=10=]) };
let storageOperation = storeData(data);
let processingOperations = data.map{ additionalProcessing([=10=]) };
... // some code to chain steps 1-3
.subscribe { (event) -> Void in
// should be called when operations from step 3 finished
}.addDisposableTo(disposeBag);
}
让我们假设 makeAPIRequest
和 additionalProcessing
return 和 Observable<SomeNotVoidType>
和 storeData
都采用数组作为其参数并且 return一个 Observable<Array>
。
这样,您可以执行以下操作:
首先,创建一个 Observables
数组,表示将单个对象发送到后端。然后使用 toObservable
方法,因此生成的信号可以稍后进行转换:
let apiOperations = data.map{ makeAPIRequest([=20=]) }.toObservable()
然后使用 merge
运算符,这将生成 Observable
,仅当所有 API 调用完成时才完成。您还可以使用 toArray
运算符,它将 API 调用结果放入一个数组中:
let resultsArray = apiOperations.merge().toArray()
这会给你一个 Observable<Array<ApiResult>>
,它会在所有 API 操作成功完成时发送一个 Next
事件。现在您可以将结果存储在数据库中:
let storedResults = resultsArray.flatMap { storeDatabase([=10=]) }
然后您又想为每个数组元素制作 Observables
,因此它们将代表额外的处理。请注意,您需要使用 flatMap
和 flatMapLates
,否则您最终会得到像 Observable<Observable<SomeType>>
.
let additionalProcessingResults = storedResults.flatMap {
return [=11=].map(additionalProcessing).toObservable()
}.flatMapLatest { return [=11=] }
然后,您可以订阅附加处理的成功完成(或者您可以对其单独的结果做一些事情):
additionalProcessingResults.subscribe { (event) -> Void in
// should be called when operations from step 3 finished
}.addDisposableTo(disposeBag);
请注意,您不需要所有中间变量,我只是让它们描述所有步骤。