Home > other >  Swift Async Await dealing with fallback scenario
Swift Async Await dealing with fallback scenario

Time:02-02

I'm getting my head around the Async Await functionality and I'm stuck on a fallback scenario involving a feed. In my refactoring a viewModel attempts to get a feed from either the network or if that fails a default fallback.

The problem my head is having is that async await is supposed to remove the nested closure issues, yet I still think it's needed in a fallback use case.

func fetch() async throws -> [Feed]? {
    var feed: [Feed]?
    do {
        feed = try await remoteLoader.load()
    } catch {
        // Pass error up the chain for handling
        do {
          feed = try await localLoader.load()
        } catch { 
        // Pass error up the chain for handling
        }
    }
    return feed
}

Is this the intended approach for fallbacks?

An alternative that I came up with would be to attempt to load the local first and then replace it with the Remote if that succeeds.

func fetch() async throws -> [Feed]? {
    var feed: [Feed]?
    do {
        feed = try await localLoader.load()
        feed = try await remoteLoader.load()
    } catch {
        throw FeedRepositoryError.FetchFeed(error)
    }
    return feed
}

CodePudding user response:

You should either return a non-optional array or an error is thrown.

The function can be reduced to

func fetch() async throws -> [Feed] 
{
    do {
        return try await remoteLoader.load()
    } catch {
        return try await localLoader.load()
    }
}

If the remote data cannot be loaded the error is being caught and the code tries to load the local data. If this also fails the error is handed over to the caller.

If remoteLoader can throw multiple errors add a second catch scope for example if there is an unavailable error to fall back

func fetch() async throws -> [Feed] 
{
    do {
        return try await remoteLoader.load()
    } catch Loader.unavailable {
        return try await localLoader.load()
    } catch {
        throw error
    }
}

You can even omit the second catch block if you catch a distinct error in the first one.

  •  Tags:  
  • Related