With SwiftCoroutine you can do next using CoFuture and coroutines:
func fetchContentsOfURL(_: URL) -> CoFuture<HTML> { ... }
func downloadImage(_: URL) -> CoFuture<Image> { ... }
func processImage(_: HTML) -> CoFuture<Result> { ... }
// not async.
func extractImageURLsFromHTML(_: HTML) -> [URL] { ... }
func getImageURLs(from url: URL) -> CoFuture<[URL]> {
CoFuture {
let html: HTML = try fetchContentsOfURL(url).await()
return extractImageURLsFromHTML(html)
}
}
func getImages(urlList: [URL]) {
let urlsFutures = urlList.map(getImageURLs) //will start in parallel
Coroutine.start {
for urlFuture in urlsFutures {
let urls: [URL] = try urlFuture.await()
for imageURL in urls {
let image: Image = try downloadImage(imageURL).await()
let result: Result = try downloadImage(image).await()
imageLibrary.addImage(result)
}
}
}
}
Or without CoFuture:
func fetchContentsOfURL(_: URL) throws -> HTML { ... }
func downloadImage(_ url: URL) throws -> Image {
let (data, _, error) = try Coroutine.await {
URLSession.shared.dataTask(with: url, completionHandler: $0).resume()
}
if let error = error { throw error }
if let image = data.map(Image.init) { return image }
throw URLError(.cannotParseResponse)
}
func processImage(_: HTML) throws -> Result { ... }
// not async.
func extractImageURLsFromHTML(_: HTML) -> [URL] { ... }
func getImages(urlList: [URL]) {
Coroutine.start {
for url in urlList {
let html = try fetchContentsOfURL(url)
for imageURL in extractImageURLsFromHTML(html) {
let image = try downloadImage(imageURL)
let result = try processImage(image)
imageLibrary.addImage(result)
}
}
}
}