如何展平AnyPublisher <AnyPublisher <>>?

时间:2019-09-06 00:13:33

标签: swift combine

我从RESTful服务器加载端点,其中一些端点是多页的。它们在标头响应中由“ x页”字段表示。我想创建一个发布者,将所有页面中的所有对象作为单个数组返回。

最后一个return语句出现编译错误。

Cannot convert return expression of type 'AnyPublisher<AnyPublisher<[T], LoadingError>, LoadingError>\' to return type 'AnyPublisher<[T], LoadingError>'

如何修复此“嵌入式”发布商?

import Combine
import Foundation

enum LoadingError: Error {
    case url(URLError)
    case decode(Error)
    case couldNotDetermieLastPageNumber(URL)
}

func multipageDataTaskPublishter<T>(for endpoint: Endpoint) -> AnyPublisher<[T], LoadingError> where T: Decodable {
    assert(endpoint.page == 1)
    let publisher = URLSession.shared.dataTaskPublisher(for: endpoint.url)
        .retry(1)
        .mapError { LoadingError.url($0) }
        .map { (arg) -> AnyPublisher<[T], LoadingError> in
            let (_, response) = arg
            guard
                let header = response as? HTTPURLResponse,
                let xpages = header.value(forHTTPHeaderField: "x-pages"),
                let lastPage = Int(xpages)
            else {
                return Fail(error: LoadingError.couldNotDetermieLastPageNumber(endpoint.url))
                    .eraseToAnyPublisher()
            }

            let publishers = (1...lastPage).map { page -> AnyPublisher<[T], LoadingError> in
                let next = endpoint.for(page: page)
                return URLSession.shared.dataTaskPublisher(for: next.url)
                    .retry(1)
                    .mapError { LoadingError.url($0) }
                    .map { $0.data }
                    .decode(type: [T].self, decoder: JSONDecoder())
                    .mapError { LoadingError.decode($0) }
                    .eraseToAnyPublisher()
            }
            return Publishers.Sequence(sequence: publishers)
                .flatMap { $0 }
                .reduce([], +)
                .eraseToAnyPublisher()
        }
    return publisher.eraseToAnyPublisher()
}

创建多页发布者时,我可以在防护之后立即添加一个Sink来读取lastPage值。然后将let publishers = ...部分从地图上抬起一层,我的Publishers.Sequence返回值将是正确的。但这在许多层面上似乎是错误的。拆分执行,不可组合。

此外,我意识到我的实现将首页加载两次。稍后拆分管道并合并数据有效负载会更好,我想使用该解决方案,但我需要先解决这个问题。如果这是一个没有希望的原因,那么就这样,任何惯用的Combine解决方案都将被接受。

1 个答案:

答案 0 :(得分:0)

此行.map { (arg) -> AnyPublisher<[T], LoadingError> in必须是flatMap