【发布时间】:2020-11-03 12:21:28
【问题描述】:
我有一个 API 可能会响应“稍后再试”。在这种情况下,我想递归调用该函数(以自动传播取消)。
简化示例:
suspend fun loadData() {
runCatching { someApi.loadData() }
.onSuccess { response ->
if (response is Response.TryAgain) {
delay(1000)
loadData()
}
}
}
如果我理解正确,这段代码不应该导致StackOverflowError(与常规的非挂起递归函数相反)。
我从the article by Roman Elizarov 得到这个想法,但我没有在这里使用DeepRecursiveFunction。
我为 Android 写了some tests,似乎:
-
suspend没有暂停点的函数在 1000-4000 左右的深度抛出StackOverflowError(就像非暂停的一样) -
suspend带有悬挂点的函数(yield()或delay())允许达到 1-2 百万的深度,其中OutOfMemoryError发生
这种行为是否记录在某处,或者它只是一个未来可能会改变的实现细节?我在coroutines design document 或coroutines guide 以及SO 上都没有找到答案。
总的来说,如果调用深度会远低于一百万,那么使用这种模式是否是个好主意?有没有更好的可取消解决方案?
【问题讨论】:
-
在这个简化的例子中,tailrec 修饰符看起来是一个完美的选择。它适合您的实际情况吗?
-
感谢您的建议!不幸的是,实际用例包括
try/catch(或runCatching),tailrec不支持。我编辑了问题以反映这一点。
标签: kotlin recursion kotlin-coroutines suspend