结合绑定 Publisher 到 PassthroughSubject

Combine bind Publisher to PassthroughSubject

这个问题之前已经被有效地问过 (),但是答案假定问题示例的架构是完全错误的。

我遇到了同样的问题,但我觉得这是一个不同的示例案例,我非常希望能清楚地说明这个问题。


我有一个视图模型 class,它为客户端层提供了一个 public errorMessage 发布者来做它想做的事情。这里只是一个字符串。私下里,这个发布者得到了 PassthroughSubject 的支持 - 我正在从内部的不同地方“进入 monad”,所以我想在那个阶段强制发送错误消息。

我在这里的一个切入点恰好是另一个 Combine 出版商。我只想映射和绑定,就像我在 RxSwift 中那样:

private let _errorMessageSubject = PublishSubject<String>()
public let errorMessageRail = _errorMessageSubject.asObservable()

private func setup() {
   ...

   myEngine.errorMessages
     .map { msg in "Internal error: \(msg)" } 
     .bind(to: _errorMessageSubject)
   
   ...
}

private func someOtherMethod() {
   _errorMessageSubject.onNext("Surprise")
}

在 Combine 中,我不知道该怎么做,除了:

private let _errorMessageSubject = PassthroughSubject<String,Never>()
public let errorMessageRail = _errorMessageSubject.eraseToAnyPublisher()

private func setup() {
   ...

   myEngine.errorMessages
     .map { msg in "Internal error: \(msg)" } 
     .sink { [weak self] msg in
         self?._errorMessageSubject.send(msg)
     }
   
   ...
}

private func someOtherMethod() {
   _errorMessageSubject.send("Surprise")
}

在我们开始讨论并发问题之前,假设我总是小心地推送到特定调度队列上的 _errorMessageSubject。为了清楚起见,我从上面的代码中省略了它。

所以给出这个例子,除非我遗漏了一些非常明显的东西,否则 flatMap 在这里帮不了我。

这听起来像是您希望您的轨道成为 _errorMessageSubject 和另一个发布者的合并。所以我将 errorMessageRail 设为一个变量,以便在初始化后可以更改它(仅通过此 class):

public private(set) var errorMessageRail = _errorMessageSubject.eraseToAnyPublisher()

然后,在设置中,您更改导轨,使其包含额外的流:

   func setup() {
        ...

        errorMessageRail = _errorMessageSubject.merge( with:
            myEngine.errorMessages
                .map { msg in "Internal error: \(msg)" }
        ).eraseToAnyPublisher()

    }