Fried Rice
Fried Rice

Reputation: 3713

Swift Combine framework multiple async request responses into one

Here is a pseudo code of what I need to achieve:

func apiRequest1() -> Future<ResultType1, Error> { ... }
func apiRequest2() -> Future<ResultType2, Error> { ... }
func transform(res1: ResultType1, res2: ResultType2) -> ResultType3 { ... }

func combinedApiRequests() -> Future<ResultType3, Error> {
    (resultType1, resultType2) = execute apiRequest1() and apiRequest2() asynchronously
    resultType3 = transform(resultType1, resultType2)
    return a Future publisher with resultType3
}

How would combinedApiRequests() look?

Upvotes: 0

Views: 1316

Answers (1)

New Dev
New Dev

Reputation: 49590

There's no need to return a Future publisher. Future publisher is a specific publisher, but as far as a downstream is concerned, a publisher is defined by its output and failure types. Instead, return a AnyPublisher<ResultType3, Error>.

Zip is a publisher that waits for all results to arrive to emit a value. This is probably what you'd need (more on this later). This is how your function could look:

func combinedApiRequests() -> AnyPublisher<ResultType3, Error> {
   Publishers.Zip(apiRequest1, apiRequest2)
             .map { transform(res1: $0, res2: $1) }
             .eraseToAnyPublisher()
}

There is also CombineLatest publisher. For the first result from each upstream, it behaves the same as Zip, but for subsequent results it differs. In your case, it doesn't matter since Future is a one-shot publisher, but if the upstream publishers emitted multiple values, then you'd have to decide for your specific use case whether to use Zip - which always waits for all upstreams to emit a value before it emits a combined value, or CombineLatest - which emits with each new upstream value and combines it with the latest for other upstreams.

Upvotes: 2

Related Questions