Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Select

Операция select ждёт, пока любой из набора фьючерсов не будет готов, и реагирует на результат этого фьючерса. В JavaScript это похоже на Promise.race. В Python аналог — asyncio.wait(task_set, return_when=asyncio.FIRST_COMPLETED).

Подобно оператору match, тело select! содержит несколько ветвей, каждая в виде pattern = future => statement. Когда future готов, его возвращаемое значение деструктурируется по pattern. Затем statement выполняется с полученными переменными. Результат statement становится результатом макроса select!.

// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0

use tokio::sync::mpsc;
use tokio::time::{Duration, sleep};

#[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!("got: {msg}"),
            _ = sleep(Duration::from_millis(50)) => println!("timeout"),
        };
    });
    sleep(Duration::from_millis(10)).await;
    tx.send(String::from("Hello!")).await.expect("Failed to send greeting");

    listener.await.expect("Listener failed");
}
This slide should take about 5 minutes.
  • Асинхронный блок listener здесь — распространённая форма: ждать какого-нибудь асинхронного события или таймаута. Измените sleep, чтобы он спал дольше, и посмотрите, как всё сломается. Почему в этой ситуации тоже не удаётся send?

  • select! также часто используется в цикле в архитектурах «акторов», где задача реагирует на события в цикле. У этого есть свои подводные камни, которые обсудим в следующем сегменте.