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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么我们在Combine中没有tryFlatMap操作符?相关的知识,希望对你有一定的参考价值。

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

答案

因为 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) }
另一答案

还有一个解决方案 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()

乱用错误类型有点烦人。

以上是关于为什么我们在Combine中没有tryFlatMap操作符?的主要内容,如果未能解决你的问题,请参考以下文章

Combine 的 receive(on:) 没有分派到串行队列,导致数据竞争

将值的动态列表传递到 Table.Combine

Xcode 11 中 Swift Combine.framework 的可选链接

如何使用 combine Publisher 更改线程?

sas,combine,未知代码数据集观察

谈谈Combine中一个有趣操作符flatMap的使用与陷阱