Swift Async Await处理回退场景

Swift Async Await dealing with fallback scenario

我正在研究异步等待功能,但我被困在涉及提要的后备方案中。在我的重构中,viewModel 尝试从网络获取提要,如果失败则默认回退。

我脑子里的问题是 async await 应该可以消除嵌套的闭包问题,但我仍然认为在后备用例中需要它。

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
}

这是回退的预期方法吗?

我想到的一个替代方法是先尝试加载本地,如果成功则用远程替换它。

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
}

您应该 return 一个 non-optional 数组,否则将引发错误。

函数可以缩减为

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

如果无法加载远程数据,则会捕获错误并且代码会尝试加载本地数据。如果这也失败,错误将移交给调用者。

如果 remoteLoader 可以抛出多个错误,则添加第二个捕获范围,例如,如果存在要回退的 unavailable 错误

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

如果您在第一个块中发现明显的错误,您甚至可以省略第二个 catch 块。