【问题标题】:ReactiveSwift pipeline flatMap body transform not executed未执行 ReactiveSwift 管道 flatMap 主体转换
【发布时间】:2021-02-28 15:26:35
【问题描述】:

我有以下管道设置,由于某种我无法理解的原因,第二个 flatMap 被跳过:

func letsDoThis() -> SignalProducer<(), MyError> {

    let logError: (MyError) -> Void = { error in
        print("Error: \(error); \((error as NSError).userInfo)")
    }

    return upload(uploads) // returns: SignalProducer<Signal<(), MyError>.Event, Never>
        .collect() // SignalProducer<[Signal<(), MyError>.Event], Never>
        .flatMap(.merge, { [uploadContext] values -> SignalProducer<[Signal<(), MyError>.Event], MyError> in
            return context.saveSignal() // SignalProducer<(), NSError>
                .map { values } // SignalProducer<[Signal<(), MyError>.Event], NSError>
                .mapError { MyError.saveFailed(error: $0) } // SignalProducer<[Signal<(), MyError>.Event], MyError>
        })
        .flatMap(.merge, { values -> SignalProducer<(), MyError> in
            if let error = values.first(where: { $0.error != nil })?.error {
                return SignalProducer(error: error)
            } else {
                return SignalProducer(value: ())
            }
        })
        .on(failed: logError)
}

查看以upload 方法开头的转换/签名。 当我说跳过时,我的意思是即使我添加断点或日志语句,它们也不会被执行。

知道如何调试或修复吗?

谢谢。

编辑:它很可能与map 和第一个flatMap 有关,但还不确定如何修复它。 看到这个link

编辑 2:版本

- ReactiveCocoa (10.1.0):
- ReactiveObjC (3.1.1)
- ReactiveObjCBridge (6.0.0):
- ReactiveSwift (6.1.0)

编辑3:我发现问题是由于我的方法saveSignal发送sendCompleted

extension NSManagedObjectContext {
 func saveSignal() -> SignalProducer<(), NSError> {
    return SignalProducer { observer, disposable in
        self.perform {
            do {
                try self.save()
                observer.sendCompleted()
            }
            catch {
                observer.send(error: error as NSError)
            }
        }
    }
}

发送完成是有意义的,所以我无法更改。有什么方法可以改变 flatMap 以仍然做我打算做的事情?

【问题讨论】:

  • 你能更详细地解释你想要做什么吗?您是要等到所有上传完成后再保存托管对象上下文,还是要在每次上传完成时保存?如果上传失败,你还想保存吗?
  • 感谢@jjoelson 的回答,我想在所有上传完成后保存,即使其中一些失败。

标签: swift flatmap reactive-swift


【解决方案1】:

我认为您的第二个flatMap 从未执行的原因是saveSignal 从不发送值;它只是以completed 事件或error 事件结束。这意味着永远不会调用map,也不会将任何值传递给您的第二个flatMap。您可以通过执行以下操作来修复它:

context.saveSignal()
    .mapError { MyError.saveFailed(error: $0) }
    .then(SignalProducer(value: values))

您无需使用map(它什么都不做,因为没有要映射的值),您只需创建一个新的生产者,在saveSignal 成功完成后发送values

【讨论】:

  • 这两个 flatMap 的扁平化策略在这种情况下有什么不同吗? latest、merge、concat 似乎没什么区别。我如何推断该选择哪一个? (此时收集后,这可能是同步的,没关系?)
  • 没错,在这种情况下它们都是一样的,因为collect 只向flatMap 发送一个值。该策略告诉flatMap 如何处理多个值。我去年写了一个答案,解释了不同的策略:stackoverflow.com/a/58615144/642233
猜你喜欢
  • 2016-12-25
  • 1970-01-01
  • 1970-01-01
  • 2019-09-30
  • 2020-02-14
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多