Hi,
Is there any way to return a value instantly and then reload the remote resources in an async/await call?
I want to serve cached response, reload remote data and return on asynchronous call finish.
Is it possible?
Thanks!
Hi,
Is there any way to return a value instantly and then reload the remote resources in an async/await call?
I want to serve cached response, reload remote data and return on asynchronous call finish.
Is it possible?
Thanks!
I see no blockers to do that. Something like:
func getValue(andUpdateIfNeeded updateCallback: @escaping (Value) -> Void) -> Value {
let cachedValue = ...
if isExpired(cachedValue) {
makeRequest(completion: { newValue in
updateCallback(newValue)
}
}
return cachedValue
}
or
func getValue() -> (cachedValue: Value, updateIfNeeded: () async -> Value?) {
}
let (cachedValue, updateIfNeeded) = getValue()
// use cached value synchronously
Task {
let updatedValue = await updateIfNeeded()
if let updatedValue {
// ...
}
}
I'd prefer the callback version with the callback which is called twice:
func getResource(url: URL, execute: @escaping (Data) -> Void) {
let cachedResponse = ...
execute(cachedResponse?.data)
reload { execute($0) }
}
print("before")
getResource { data in
print("got data")
}
print("after")
Outputs:
The async/await version of that could be done to make the use sites like so:
print("before")
for await data in url.asyncData {
print("got data")
}
print("after")
with "got data" printed twice, first with cached data then with the new data after reload. Note that in this case the output would be:
Thanks @Dmitriy_Ignatyev and @tera
Looking at your suggestions, I think I've found the solution:
extension URLSession {
func cachedDataAndReloadStream(for request: URLRequest) -> AsyncStream<(Data, URLResponse)> {
AsyncStream<(Data, URLResponse)> { continuation in
// Return cache
if let cached = URLCache.shared.cachedResponse(for: request) {
continuation.yield((cached.data, cached.response))
}
// Reload
Task {
let response = try await URLSession.shared.data(for: request)
continuation.yield(response)
continuation.finish()
}
}
}
}
let request = makeRequest(baseURLString: "https://www.google.es")
for await response in URLSession.shared.cachedDataAndReloadStream(for: request) {
// First cache, then reloaded
}