0

我有一个关于 Swift 3 的 ReactiveCocoa (v5) 的问题。在我的项目中,我有不同的服务。例如 api 或用于从磁盘保存或获取内容。这些服务正在返回 SignalProducer。我现在有一些类似调用不同服务的序列,这些服务相互依赖。这里的顺序:

  1. 调用服务获取密钥
  2. 使用 key 调用 api 和 service
  3. 获取数据表单 api(返回多个模型)
  4. 使用 first-model-service 保存第一个模型
  5. 使用 second-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这里的功能是否正确。

有没有人和我一样的情况,可以举个例子吗?我阅读了一些教程,但我无法弄清楚。

4

1 回答 1

1

您说得对,如果SignalProducer序列中的任何一个 s 失败,则以下块都不会执行,执行将直接跳到startWithFailed.

如果keyService失败,我们不能使用dataService,如果dataService失败,我们不能保存任何一个模型,所以这种行为对于这两个操作是有意义的。

但是,这些modelService操作不相互依赖才能完成,因此应该在我们的信号模型中同时执行。要按顺序执行,您已经知道如何使用- 使用orflatMap并发执行同样容易(请参阅文档)。通过与/并发执行模型服务操作,我们也可以免费进入正确的范围。zipcombineLatestzipcombineLatestdata

使用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.savemodelService2.save

回覆:startWithFailed

当您启动信号生成器时,您选择启动它的函数将定义回调块中的代码处理哪些事件。如果您从SignalProducerwith开始,startWithFailed那么只有错误会导致您的完成块被调用。

像这样的操作的最佳选择通常startWithResult是将 a 传递Result<Value, Error>到您的完成块并在每个.value.failed事件上调用您的完成块。

但是,如果您不想对成功的 fetch & save 采取任何操作而只需要处理错误,那么startWithFailed确实是正确的选择。

于 2018-04-02T23:19:39.077 回答