【问题标题】:Chaining n requests in Combine [duplicate]在组合中链接n个请求[重复]
【发布时间】:2021-12-14 20:38:52
【问题描述】:

我正在尝试将n 请求与Combine 链接起来。

假设我有 50 个用户,我需要为每个用户执行一个请求来获取用户数据。我知道使用flatMap 您可以将一个Publisher 结果传递给下一个。但这也适用于循环吗?

这是我获取用户的功能:

func fetchUser(for id: Int) -> AnyPublisher<User, Error> {
    let url = "https://user.com/api/user/\(id)"
    return URLSession.shared.dataTaskPublisher(for: url)
        .mapError { $0 as Error }
        .map { $0.data }
        .decode(type: User.self, decoder: JSONDecoder())
        .eraseToAnyPublisher()
}

所以基本上我需要另一个函数,它在这个fetchUser 上循环它并在一个结果数组中返回所有用户。这些请求不应同时运行,而应在前一个请求完成后启动一个。

【问题讨论】:

    标签: swift combine urlsession


    【解决方案1】:

    对于这个,很大程度上取决于您希望如何使用 User 对象。如果您希望他们在进来时都作为单独的用户发出,那么merge 是解决方案。如果您想保持数组顺序并在用户全部进入后将它们全部作为用户数组发出,那么combineLatest 就是您所需要的。

    由于您正在处理一个数组,并且 merge 和 combineLatest 都没有数组版本,因此您需要使用 reduce。以下是示例:

    func combine(ids: [Int]) -> AnyPublisher<[User], Error> {
        ids.reduce(Optional<AnyPublisher<[User], Error>>.none) { state, id in
            guard let state = state else { return fetchUser(for: id).map { [$0] }.eraseToAnyPublisher() }
            return state.combineLatest(fetchUser(for: id))
                .map { $0.0 + [$0.1] }
                .eraseToAnyPublisher()
        }
        ?? Just([]).setFailureType(to: Error.self).eraseToAnyPublisher()
    }
    
    func merge(ids: [Int]) -> AnyPublisher<User, Error> {
        ids.reduce(Optional<AnyPublisher<User, Error>>.none) { state, id in
            guard let state = state else { return fetchUser(for: id).eraseToAnyPublisher() }
            return state.merge(with: fetchUser(for: id))
                .eraseToAnyPublisher()
        }
        ?? Empty().eraseToAnyPublisher()
    }
    

    请注意,在组合情况下,如果数组为空,则发布者将发出一个空数组然后完成。在合并的情况下,它只会完成而不发出任何东西。

    还要注意,在任何一种情况下,如果任何发布者失败,则整个链将关闭。如果您不希望这样,您将不得不捕获错误并对其进行处理...

    【讨论】:

    • 这两个操作符都在CombineExt 中实现了,比我上面总结的要干净得多。
    猜你喜欢
    • 1970-01-01
    • 2011-11-10
    • 2012-11-16
    • 2017-08-13
    • 1970-01-01
    • 2015-04-22
    • 2016-07-31
    • 1970-01-01
    • 2023-03-11
    相关资源
    最近更新 更多