Use the flatMap operator in Combine to transform elements from a publisher to another publisher.
import Combine
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let idPublisher = (1...5).publisher
var cancellables = Set<AnyCancellable>()
func fetchUserDetails(userId: Int) -> AnyPublisher<String, Never> {
let detail = "User details for \(userId)"
return Just(detail)
.delay(for: .milliseconds(userId * 1000), scheduler: RunLoop.main)
.eraseToAnyPublisher()
}
print("\(Date()) : Starting")
idPublisher
.flatMap(maxPublishers: .max(1)) { fetchUserDetails(userId: $0) }
.sink { print("\(Date()) : \($0)") }
.store(in: &cancellables)
In the above code:
- The
idPublisheremits three elements: 1, 2, and 3. - The
fetchUserDetailsfunction takes anIntas input and returns a publisher that emits a string. - The
flatMapoperator transforms the elements from theidPublisherto another publisher using thefetchUserDetailsfunction. - Them
maxPublishersparameter is used to specify the maximum number of publishers that can be active at a time. In this case, it is set to.max(1), which means only one publisher can be active at a time. - The
sinkoperator subscribes to the publisher and prints the emitted values. - The
delayoperator is used to simulate a network request with a delay based on the user id.
When you run the code, you will see the following output:
2024-12-18 06:56:20 +0000 : Starting
2024-12-18 06:56:21 +0000 : User details for 1
2024-12-18 06:56:23 +0000 : User details for 2
2024-12-18 06:56:26 +0000 : User details for 3
2024-12-18 06:56:30 +0000 : User details for 4
2024-12-18 06:56:35 +0000 : User details for 5
In the above example, the maxPublishers parameter is set to .max(1), which means only one publisher can be active at a time. This ensures that the fetchUserDetails function is called sequentially for each element emitted by the idPublisher.
If the maxPublishers parameter is set to .max(2), two publishers can be active at a time, and the fetchUserDetails function will be called concurrently for two elements emitted by the idPublisher. Once one of the publishers completes, the next publisher will be activated.
In this example since we are using a delay to simulate a network request, the timing of printed values will be as follows.
User details for 1will be printed after 1 second.User details for 2will be printed after 2 seconds, but it will start when1completes. So it will be printed after 3 seconds.User details for 3will be printed after 3 seconds, but it will start when2completes. So it will be printed after 6 seconds.User details for 4will be printed after 4 seconds, but it will start when3completes. So it will be printed after 10 seconds.User details for 5will be printed after 5 seconds, but it will start when4completes. So it will be printed after 15 seconds.