صفات Async
متدهای Async در traitها اخیراً در انتشار 1.75 تثبیت شدهاند. این نیاز به پشتیبانی برای استفاده از موقعیت بازگشتی impl Trait
(RPIT) در traitها را داشت، زیرا شیرینزدایی (desugaring) برای async fn
شامل -> impl Future<Output = ...>
است.
با اینحال، حتی با پشتیبانی native امروز، برخی از مشکلات در مورد async fn
و RPIT در ویژگیها وجود دارد:
-
Return-position impl Trait تمام طول عمرهای درون محدوده را ثبت می کند (بنابراین برخی از الگوهای قرض کردن (borrowing) نمی توانند بیان شوند)
-
ویژگیهایی که متدهای آنها از موقعیت بازگشتی
impl trait
یاasync
استفاده میکنند باdyn
سازگار نیستند.
If we do need dyn
support, the crate async_trait provides a workaround through a macro, with some caveats:
use async_trait::async_trait; use std::time::Instant; use tokio::time::{sleep, Duration}; #[async_trait] trait Sleeper { async fn sleep(&self); } struct FixedSleeper { sleep_ms: u64, } #[async_trait] impl Sleeper for FixedSleeper { async fn sleep(&self) { sleep(Duration::from_millis(self.sleep_ms)).await; } } async fn run_all_sleepers_multiple_times( sleepers: Vec<Box<dyn Sleeper>>, n_times: usize, ) { for _ in 0..n_times { println!("running all sleepers.."); for sleeper in &sleepers { let start = Instant::now(); sleeper.sleep().await; println!("slept for {}ms", start.elapsed().as_millis()); } } } #[tokio::main] async fn main() { let sleepers: Vec<Box<dyn Sleeper>> = vec![ Box::new(FixedSleeper { sleep_ms: 50 }), Box::new(FixedSleeper { sleep_ms: 100 }), ]; run_all_sleepers_multiple_times(sleepers, 5).await; }
-
استفاده از
async_trait
آسان است، اما توجه داشته باشید که برای رسیدن به این هدف از heap allocationها استفاده میکند. این heap allocation دارای سربار عملکرد است. -
چالشهای پشتیبانی برای
async trait
در زبان Rust بسیار عمیق هستند و احتمالاً ارزش توصیف عمیق در اینجا را ندارند. Niko Matsakis در این پست آنها را به خوبی توضیح داده است. به خصوص اگر شما به این موضوع علاقهمند هستید. -
سعی کنید یک sleep خواب جدید ایجاد کنید که برای مدت زمان تصادفی میخوابد و آن را به Vec اضافه کنید.