Is there a way to attach a timeout to stop an async function if it takes too long?
Here's a simplified version of my code:
func search() async -> ResultEnum {
// Call multiple Apis one after the other
}
Task.init {
let searchResult = await search()
switch searchResult {
// Handle all result scenarios
}
}
I would like to have a deadline for the search() async
function to provide a result, otherwise it should terminate and return ResultEnum.timeout
.
Thank you Rob for your comments, and for the link you provided.
I had to make some changes though, For some reason the initial task fetchTask
kept going even after cancellation, until I added Task.checkCancellation()
to it.
Here's what the code looks like now, if anyone is facing a similar issue:
func search() async throws -> ResultEnum {
// This is the existing method as per my initial question.
// It calls multiple Apis one after the other, then returns a result.
}
// Added the below method to introduce a deadline for search()
func search(withTimeoutSecs: Int) async {
let fetchTask = Task {
let taskResult = try await search()
try Task.checkCancellation()
// without the above line, search() kept going until server responded long after deadline.
return taskResult
}
let timeoutTask = Task {
try await Task.sleep(nanoseconds: UInt64(withTimeoutSecs) * NSEC_PER_SEC)
fetchTask.cancel()
}
do {
let result = try await fetchTask.value
timeoutTask.cancel()
return result
} catch {
return ResultEnum.failed(NetworkError.timeout)
}
}
// Call site: Using the function (withTimeout:) instead of ()
Task.init {
let searchResult = await search(withTimeoutSecs: 6)
switch searchResult {
// Handle all result scenarios
}
}