创建一个发布者,该发布者在另一个发布者完成时发出值

Nic*_*ick 0 swift combine

我有一个从不发出项目并且仅完成或失败并出现错误 ( AnyPublisher<Never, Error>) 的发布者。AnyPublisher<Value, Error>我想将该发布者转换为在第一个发布者完成 ( ) 或传递任何错误时发出值的发布者。我想在第一个发布商完成后创造该价值。我可以做这样的事情,但看起来很混乱:

func demo() -> AnyPublisher<Int, Error> {
    // Using Empty just for demo purposes
    let firstPublisher = Empty<Never, Error>(completeImmediately: true).eraseToAnyPublisher()
    var cancellable: AnyCancellable?
    return Future<Int, Error> { promise in
        cancellable = firstPublisher
            .sink { completion in
                switch completion {
                case .failure(let error):
                    promise(.failure(error))
                case .finished:
                    // some operation that generates value
                    let value:Int = 1
                    promise(.success(value))
                }
            } receiveValue: { _ in
            }
    }
    .handleEvents(receiveCancel: {
        cancellable?.cancel()
    })
    .eraseToAnyPublisher()
}
Run Code Online (Sandbox Code Playgroud)

这可以用更好的方法来完成吗?就像是:

extension AnyPublisher {
    func completionMap<T, P>(_: (_ completion: Subscribers.Completion<Self.Failure>) -> P) -> P where P: Publisher, T == P.Output, Self.Failure == P.Failure {
        /// ???
    }
}
func demo() -> AnyPublisher<Int, Error> {
    // Using Empty just for demo purposes
    let firstPublisher = Empty<Never, Error>(completeImmediately: true).eraseToAnyPublisher()
    return firstPublisher
        .completionMap { completion -> AnyPublisher<Int, Error> in
            switch completion {
            case .failure(let error):
                return Fail(error: error).eraseToAnyPublisher()
            case .finished:
                // some operation that generates value
                let value:Int = 1
                return Just(value).setFailureType(to: Error.self).eraseToAnyPublisher()
            }
    }.eraseToAnyPublisher()
}
Run Code Online (Sandbox Code Playgroud)

New*_*Dev 5

您可以使用.append(返回 a Publishers.Concatenate)作为在第一个发布者完成后发出值的方式。

let firstPublisher: AnyPublisher<Never, Error> = ...


let demo = firstPublisher
   .map { _ -> Int in }
   .append([1])
Run Code Online (Sandbox Code Playgroud)

1如果成功完成,上面的内容将会发出firstPublisher,否则会出错。