为等待函数添加超时的最佳方法是什么?
Example:
/// lets pretend this is in a library that I'm using and I can't mess with the guts of this thing
func fetchSomething() async -> Thing? {
// fetches something
}
// if fetchSomething() never returns then doSomethingElse() is never ran. Is there anyway to add a timeout to this system?
let thing = await fetchSomething()
doSomethingElse()
我想让系统在 fetchSomething() 永远不会返回的情况下更加健壮。如果这是使用组合,我会使用超时运算符。
最佳答案
可以创建一个任务
,然后如果它在特定时间段内没有完成则取消
它。例如,并行启动两个任务:
// cancel the fetch after 2 seconds
func fetchSomethingWithTimeout() async throws -> Thing {
let fetchTask = Task {
try await fetchSomething()
}
let timeoutTask = Task {
try await Task.sleep(nanoseconds: 2 * NSEC_PER_SEC)
fetchTask.cancel()
}
let result = try await fetchTask.value
timeoutTask.cancel()
return result
}
// here is a random mockup that will take between 1 and 3 seconds to finish
func fetchSomething() async throws -> Thing {
let duration: TimeInterval = .random(in: 1...3)
try await Task.sleep(nanoseconds: UInt64(TimeInterval(NSEC_PER_SEC) * duration))
return Thing()
}
如果 fetchTask
先完成,它将到达 timeoutTask.cancel
并停止它。如果 timeoutTask
先完成,它将取消 fetchTask
。
显然,这取决于 fetchTask
的实现。它不仅应该检测取消,还应该在取消时抛出错误(可能是 CancellationError
)。如果没有有关 fetchTask
实现的详细信息,我们无法进一步发表评论。
例如,在上面的例子中,我不会返回一个可选的Thing?
,而是返回Thing
,但让它throw
如果取消则出错。
我犹豫要不要提它,但是虽然上面假设 fetchSomething
表现良好(即可取消),但即使它不工作(即运行doSomethingElse
在一些合理的时间表中,即使 fetchSomething
“永远不会返回”)。
但这本质上是一种不稳定的情况,因为 fetchSomething
使用的资源在它完成之前无法恢复。 Swift 不提供抢先取消,因此虽然我们可以轻松解决确保 doSomethingElse
最终运行的战术问题,但如果 fetchSomething
可能永远不会在某个合理的时间表内完成,您有更深层次的问题。
你真的应该找到一个可取消的 fetchSomething
版本,如果它还没有的话。
https://stackoverflow.com/questions/74710155/
相关文章:
python - Pandas dataframe,连续查找所选列中的最大值,并根据该值查找另一列的
python - ModuleNotFoundError 即使模块被识别
node.js - 为什么当我使用 "waitForSelector"时 Puppeeteer 导致
haskell - 如何测试自定义 StateT 的 Monad 实例?
javascript - 是的,当 .required() 为 false 时,会继续在同一个属性上
windows-installer - 在 Windows 的添加/删除程序中显示正确的大小