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; use tokio::time::{sleep, Duration}; #[tokio::main] async fn main() { let (tx, mut rx) = mpsc::channel(32); let listener = tokio::spawn(async move { tokio::select! { Some(msg) = rx.recv() => println!("отримав: {msg}"), _ = sleep(Duration::from_millis(50)) => println!("тайм-аут"), }; }); sleep(Duration::from_millis(10)).await; tx.send(String::from("Привіт!")).await.expect("Не вдалося надіслати привітання."); listener.await.expect("Listener зазнав невдачі"); }
-
Блок асинхронізації
listener
тут є звичайною формою: очікування деякої асинхронної події або таймауту. Змінітьsleep
на довший час, щоб побачити, що він не спрацює. Чому в цій ситуації також не спрацьовуєsend
? -
Команда
select!
також часто використовується у циклі в "actor" архітектурах, де завдання реагує на події у циклі. Це має деякі підводні камені, які буде обговорено у наступному розділі.