使用 Combine Framework 的 Publisher mapError

Publisher mapError with the Combine Framework

我有这样的设置,错误如下所示

enum DataError: Error {
    case failed(error: Error)
}

enum UIError: Error {
    case failed(error: Error)
}

struct SomeData {

}

func foo() -> AnyPublisher<Result<[SomeData]?, DataError>, Never> {
    ...
}

func foo2() -> AnyPublisher<Result<[SomeData]?, UIError>, Never> {
    return foo()
            .mapError { error -> UIError 
                switch error {
                    ....
                }

                return UIError.failed(error: [=10=])
            }
            .eraseToAnyPublisher() ===> // Error Cannot convert return expression of type 'AnyPublisher<Result<[SomeData]?, DataError>, UIError>' to return type 'AnyPublisher<Result<[T], UIError>, Never>'
}

错误消息看起来很简单,但无法完全解决。

Combine 中使用 Result 毫无意义,因为您的 Publisher 总是要么发出一个值,要么以失败告终。它们永远不应该发出包含错误的值。

一旦您不再使用 Result,错误就会消失。

func foo() -> AnyPublisher<[SomeData], DataError> {
    ...
}

func foo2() -> AnyPublisher<[SomeData], UIError> {
    return foo()
        .mapError { error -> UIError in
            switch error {
            ...
            }

            return UIError.failed(error: error)
        }
        .eraseToAnyPublisher()
}

无论是 Result 还是在 Publisher 中,您通常都不需要使用 Optionals,因为如果出现错误,根本就没有值,与完成处理程序不同,不需要 return nil 值。

您可能需要这样的东西:

发布者returns没有错误。结果有错误,因此您需要对结果进行 mapError。

我修改了错误枚举,使其更容易理解。

    enum DataError: Error {
        case failed
    }

    enum UIError: Error {
        case failed
    }

    func foo2() -> AnyPublisher<Result<[SomeData]?, UIError>, Never> {
        return foo().map { result in
            result.mapError { _ -> UIError in
                UIError.failed
            }
        }.eraseToAnyPublisher()
    }