我有一个关于 ReactiveCocoa (v5) 与 Swift 3 的问题。在我的项目中,我有不同的服务。例如,API 或用于从磁盘保存或获取内容的 API。这些服务正在返回 SignalProducer。我现在有类似调用相互依赖的不同服务的序列。顺序如下:
- 调用服务获取 key
- 使用key调用service的api
- 从 api 获取数据(返回多个模型)
- 使用first-model-service保存第一个模型
- 使用 secondary-model-service 保存第二个模型
在我的序列中,我还必须将第二个服务调用的数据传递到模型保存中。
keyService.get().flatMap(.latest) { (key) -> SignalProducer<[Data],Error> in
return self.dataService.get()(key: key)
}
.flatMap(.latest) { (data) -> SignalProducer<Bool, Error> in
return self.firstModelService.save(data["Model1"])
}
.flatMap(.latest) { (data) -> SignalProducer<Bool, Error> in
//how to get data here?
return self.secondModelService.save(data["Model2"])
}.startWithFailed({ e in
})
此外,如果序列中的一个 SignalProducer
发送错误,则整个序列将停止,并以错误作为参数调用回调。我不知道 startWithFailed
是否是正确的函数。
有人有和我类似的情况吗,可以举个例子吗?我读了一些教程,但我无法弄清楚。
最佳答案
您的说法是正确的,如果 SignalProducer
中的任何一个沿着序列失败,后面的 block 都不会执行,执行将直接跳到 startWithFailed
中的 block .
如果keyService
失败了,我们不能使用dataService
,如果 dataService
失败,我们无法保存任何一个模型,因此此行为对于这两个操作是有意义的。
但是,modelService
操作不依赖于彼此来完成,因此应该在我们的信号模型中同时执行。要按顺序执行,您已经知道使用 flatMap
- 使用 zip
并发执行同样容易或combineLatest
(参见documentation)。通过与 zip
同时执行模型服务操作/combineLatest
,我们还得到data
在正确的范围内免费。
使用combineLatest
,你的代码变成:
keyService.get().flatMap(.latest) { (key) -> SignalProducer<[Data],Error> in
return self.dataService.get()(key: key)
}.flatMap(.latest) { (data) -> SignalProducer<(Bool, Bool), Error> in
return SignalProducer.combineLatest(
self.firstModelService.save(data["Model1"]),
self.secondModelService.save(data["Model2"])
)
}
您可以看到生成的信号生成器现在有 Value
(Bool, Bool)
的类型,分别表示modelService1.save
的结果和modelService2.save
回复:startWithFailed
当您启动信号生成器时,您选择启动它的函数将定义回调 block 中的代码处理哪些事件。如果您启动SignalProducer
与 startWithFailed
那么只有错误才会导致您的完成 block 被调用。
此类操作的最佳选择通常是 startWithResult
它通过 Result<Value, Error>
进入您的完成 block 并在每个 .value
上调用您的完成 block 或.failed
事件。
但是,如果您不想在成功获取和保存时采取任何操作,而只需要处理错误,那么startWithFailed
确实是正确的选择。
关于swift - ReactiveCocoa - 具有一般错误处理功能的信号生成器序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44366975/