我正在将应用程序的网络转换为使用warec/await,在找到一个令人满意的模式来替换我们之前使用的完成处理程序时遇到了一些麻烦.以下是我们所做的一些伪代码:
func loadData() {
fetchData {
showTheSearchField()
}
}
func fetchData(completion: () -> ()) {
doTheActualNetworking()
if networkingSucceeded {
completion()
} else {
putUpAnAlertWithATryAgainButton(buttonAction: {
fetchData(completion: completion)
}
}
}
你明白重点了.首先,我们try 获取数据,这是通过执行实际联网来实现的.然后:
-
如果我们成功了,如果我们成功了,only,那么在成功的情况下做呼叫者想要做的任何事情(我称之为
completion
,但也许更好的名字是onSuccess
). -
如果我们失败了,用一个重试按钮发出警告,该按钮的作用是获取数据again,并以同样的方式again的行为-如果我们这次成功,only如果我们这次成功,那么在成功的情况下执行调用者想要做的任何事情.
我的问题是,当我转换为Await时,我找不到一种方法来消除被炸毁的完成处理程序.例如,在我的示例中,完成处理程序说要显示搜索字段.我不能简单地把整件事概括为例如一个抛出的方法:
func loadData() {
Task {
try await fetchData()
showTheSearchField()
}
}
func fetchData() async throws {
do {
try await doTheActualNetworking()
} catch {
putUpAnAlertWithATryAgainButton(buttonAction: {
Task {
try await fetchData()
}
}
throw error
}
}
你知道这有什么不对吗?如果我们第一次在doTheActualNetworking
上成功,那么我们回到loadData
中的任务,然后继续显示搜索字段.但如果我们失败并发出alert ,用户点击重试按钮,这次我们成功了,我们won't显示搜索字段,因为我们失败并抛出和loadData
结束.
因此,在我看来,由于重试按钮的循环性质,我是forced来维护完成/成功处理程序,将其传递给fetchData
,以便重试按钮可以与其一起递归,就像我之前所做的那样.
当然,这很好用,但我觉得这是一种反模式.我之所以采用异步/等待,正是因为我希望在有生之年再也不想看到另一个完成处理程序.我只是被完成处理程序卡住了,还是有什么我看不到的解决方法?