为什么我们在Combine中没有tryFlatMap操作符?

问题描述 投票:-5回答:1

我们应该用什么来代替呢?我很惊讶以前没有人问过这个问题。

swift combine
1个回答
3
投票

因为 flatMap的transform返回一个发布者,你不需要严格地使用 tryFlatMap. 您可以使用 do/catch 并返回一个 Fail 如果你发现了错误,可以向出版商咨询。

import Combine

func someFunction(of i: Int) throws -> AnyPublisher<Int, Error> {
    return Just(i + 1)
        .setFailureType(to: Error.self)
        .eraseToAnyPublisher()
}

let upstream: AnyPublisher<Int, Error> = Just(100)
    .setFailureType(to: Error.self)
    .eraseToAnyPublisher()

upstream
    .flatMap({ i -> AnyPublisher<Int, Error> in
        do {
            return try someFunction(of: i).eraseToAnyPublisher()
        } catch {
            return Fail(error: error).eraseToAnyPublisher()
        }
    })

你可以写你自己的 tryFlatMap 如果你喜欢的话,操作者。

extension Publisher {
    func tryFlatMap<Pub: Publisher>(
        _ transform: @escaping (Output) throws -> Pub
    ) -> Publishers.FlatMap<AnyPublisher<Pub.Output, Error>, Self> {
        return flatMap({ input -> AnyPublisher<Pub.Output, Error> in
            do {
                return try transform(input)
                    .mapError { $0 as Error }
                    .eraseToAnyPublisher()
            } catch {
                return Fail(outputType: Pub.Output.self, failure: error)
                    .eraseToAnyPublisher()
            }
        })
    }
}

然后像这样使用它

upstream
    .tryFlatMap { try someFunction(of: $0) }

0
投票

还有一个解决方案 tryFlatMap = tryMap + flatMap.

举个例子。整个故事的开始,我只是想解开一个可选的。而如果它是nil,我希望它只是失败。

let upstream = Just(siteURL)
    .tryMap { url -> URL in
        guard let url = url else { throw Errors.invalidSiteURL }
        return url
    }
    .flatMap {
        URLSession.shared.dataTaskPublisher(for: $0).mapError { $0 as Error }
    }

编辑】像这样也可以。

let container = Just(siteURL)
    .tryMap { url -> URLSession.DataTaskPublisher in
        guard let url = url else { throw Errors.invalidSiteURL }
        return URLSession.shared.dataTaskPublisher(for: url)
    }
    .map { $0.mapError { $0 as Error } }
    .switchToLatest()

乱用错误类型有点烦人。

© www.soinside.com 2019 - 2024. All rights reserved.