在JS:中重建setInterval
pub async fn set_interval<T, F>(interval: Duration, do_something: T)
where
T: (Fn() -> F) + Send + Sync + 'static,
F: Future + Send,
{
let forever = task::spawn(async move {
let mut interval = time::interval(interval);
loop {
interval.tick().await;
do_something().await;
}
});
forever.await;
}
这是可行的,但我希望它能够.await
,直到第一次执行结束。
即不做:
do_something().await
set_interval(Duration::from_secs(1), do_something)
我想:
set_interval(Duration::from_secs(1), do_something).await
请注意,这与上面的行为不同,因为它立即运行do_something
任务,但这是有意的。
我的解决方案:
pub async fn set_interval<T, F>(interval: Duration, do_something: T)
where
T: (Fn() -> F) + Send + Sync + 'static,
F: Future + Send,
{
do_something().await;
task::spawn(async move {
let forever = task::spawn(async move {
let mut interval = time::interval(interval);
loop {
interval.tick().await;
do_something().await;
}
});
forever.await;
});
}
这是有效的,但我有一些疑问
- 这里两次
task::spawn
是浪费资源吗?有没有办法只做一次 - 函数一结束就丢弃外部
task::spawn
是错误的吗?它会无限期地运行吗,即使它不再被跟踪,只是被解雇和遗忘了
回答您的两个问题:
- 不要担心产生太多任务:在你的普通硬件上,你应该能够每秒产生100000个任务。不过,在这种情况下没有必要,因为:
- 任务得到"分离的";如果它们被丢弃,那么运行时将继续轮询其中的期货。这也意味着您不需要
forever.await
以下似乎有效:
pub async fn set_interval<T, F>(interval: std::time::Duration, do_something: T)
where
T: (Fn() -> F) + Send + Sync + 'static,
F: std::future::Future + Send,
{
// The interval time alignment is decided at construction time.
// For all calls to be evenly spaced, the interval must be constructed first.
let mut interval = tokio::time::interval(interval);
// The first tick happens without delay.
// Whether to tick before the first do_something or after doesn't matter.
interval.tick().await;
do_something().await;
tokio::task::spawn(async move {
loop {
interval.tick().await;
do_something().await;
}
});
}
游乐场