I am currently using combine and URLSession.shared.dataTaskPublisher to do a request dependency. The first call gets an id either from cache or from a database which is then used in the second call. The application I am making can call the first function to get the id required at any time and multiple times at the same time. What I would like to do is when the First call goes out to the database to get the id for all other calls to wait before calling on this function. Is it ideal to have lock before calling on the function or if there is a better way that I am not thinking about? Thank you for your help!
Edit: I understand Combine uses a locking mechanism going down the pipeline, however, would it follow the same rule if multiple functions are calling the getId function in terms of waiting for a response? I am thinking of the approach of if I am the second or third function calling getId and the function is already working to get the id, I want to wait until I can just pull it from the cache.
Code:
override func viewDidLoad() {
super.viewDidLoad()
if let url = URL(string: "https://some url") {
self.cancellable = self.getId()
.flatMap { id in
return self.testDetails(for: id)
}
.sink(receiveCompletion: { completion in
}) { testObject in
print(testObject.name)
}
}
}
func getId() -> AnyPublisher<String, ClientError> {
//lock here? so other calls can wait to check if the id is in the cache once unlocked?
//do some stuff to get from cache
if cachedId != nil {
return Just.init(cachedId)
.mapError({ never -> ClientError in
ClientError.init("Some error has occured")
})
.eraseToAnyPublisher()
}
return URLSession.shared.dataTaskPublisher(for: url)
.map { $0.data }
.decode(type: [TestObject].self, decoder: JSONDecoder())
.tryMap { testObjects in
guard let id = testObjects.first?.id else {
throw ClientError.init("Some error has occured")
}
return id
}
.eraseToAnyPublisher()
}
func testDetails(for id: Int) -> AnyPublisher<Post, Error> {
let url = URL(string: "https://jsonplaceholder.typicode.com/posts/\(id)")!
return URLSession.shared.dataTaskPublisher(for: url)
.mapError { $0 as Error }
.map { $0.data }
.decode(type: Post.self, decoder: JSONDecoder())
.eraseToAnyPublisher()
}