Swift异步等待处理备用方案

3

我正在学习异步等待功能,但遇到了一个涉及feed的备用场景问题。在重构中,viewModel尝试从网络获取feed,如果失败,则使用默认的备用feed。

问题是,我的头脑认为异步等待应该解决嵌套闭包问题,但在备用情况下仍然需要它。

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
}
1个回答

4

您应该返回一个非可选数组,否则将抛出错误。

该函数可以简化为

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块中捕获到一个不同的错误,你甚至可以省略第二个块。


谢谢!所以,为了澄清一下,localLoader和remoteLoader会将任何错误抛出到viewModel中,我不需要在这个方法中处理它们的特定情况吗? - Warve
不,remoteLoader的错误在catch块中处理。如果remoteLoader抛出了应该传递给调用者的不同错误,您需要添加第二个catch分支。在这个范围内重新抛出错误。 - vadian
是的,这就是我一直在苦恼的问题。你确实需要嵌套“do catch”块来处理错误。 - Warve
请查看编辑。 - vadian
真是令人惊讶,你会忘记什么,第二个catch块解决了混淆的问题。将其标记为答案。谢谢+1 - Warve

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接