Select
Операція select очікує, поки будь-який із набору ф’ючерсів буде готовий, і відповідає на результат цього ф’ючерсу. У JavaScript це схоже на Promise.race
. У Python це порівнюється з asyncio.wait(task_set, return_when=asyncio.FIRST_COMPLETED)
.
Подібно до оператора порівняння, тіло select!
має кілька гілок, кожен з яких має вигляд pattern = future => statement
. Коли future
готовий, його значення, що повертається, деструктурується за допомогою pattern
. Потім виконується statement
з отриманими змінними. Результат statement
стає результатом макросу select!
.
use tokio::sync::mpsc::{self, Receiver}; use tokio::time::{sleep, Duration}; #[derive(Debug, PartialEq)] enum Animal { Cat { name: String }, Dog { name: String }, } async fn first_animal_to_finish_race( mut cat_rcv: Receiver<String>, mut dog_rcv: Receiver<String>, ) -> Option<Animal> { tokio::select! { cat_name = cat_rcv.recv() => Some(Animal::Cat { name: cat_name? }), dog_name = dog_rcv.recv() => Some(Animal::Dog { name: dog_name? }) } } #[tokio::main] async fn main() { let (cat_sender, cat_receiver) = mpsc::channel(32); let (dog_sender, dog_receiver) = mpsc::channel(32); tokio::spawn(async move { sleep(Duration::from_millis(500)).await; cat_sender.send(String::from("Фелікс")).await.expect("Не вдалося відправити кота."); }); tokio::spawn(async move { sleep(Duration::from_millis(50)).await; dog_sender.send(String::from("Рекс")).await.expect("Не вдалося відправити собаку."); }); let winner = first_animal_to_finish_race(cat_receiver, dog_receiver) .await .expect("Не вдалося отримати переможця"); println!("Переможцем стає {winner:?}"); }
-
У цьому прикладі ми маємо перегони між котом і собакою.
first_animal_to_finish_race
слухає обидва канали та вибере того, який прибуде першим. Оскільки собаці потрібно 50 мс, вона виграє у кота, якому потрібно 500 мс. -
У цьому прикладі ви можете використовувати канали
oneshot
, оскільки канали мають отримувати лише одинsend
. -
Спробуйте додати дедлайн до перегонів, продемонструвавши вибір різних видів ф’ючерсів.
-
Зауважте, що
select!
відкидає непорівнянні гілки, що скасовує їхні ф’ючерси. Його найлегше використовувати, коли кожне виконання командиselect!
створює нові ф’ючерси.- Альтернативою є передача
&mut future
замість самого ф’ючерса, але це може призвести до проблем, які далі обговорюються на слайді про закріплення.
- Альтернативою є передача