await à Rust

Nilesh Katuwal 18 aout 2022
await à Rust

Dans cet article, nous allons apprendre la signification de await en Rust.

await en Rust

async-await est une technique d’écriture de fonctions qui peuvent faire une pause, céder le contrôle à l’exécution, puis reprendre l’exécution là où elles se sont arrêtées. En règle générale, ces pauses sont utilisées pour attendre les E/S, mais elles peuvent servir à diverses fins.

async-await peut vous être familier avec JavaScript ou C#. Cependant, l’implémentation de la fonctionnalité par Rust comporte quelques changements importants.

Pour utiliser async-wait, vous devez remplacer fn par async fn :

async fn new_fxn() -> u32 { .. }

Contrairement à une fonction classique, l’appel d’un async fn n’a pas d’effet immédiat. Il renvoie un future à la place.

Le calcul est suspendu et attend d’être exécuté. Utilisez l’opérateur .await pour exécuter le future :

async fn second_fxn () {
    let future = new_fxn();

    let result: u32 = future.await;
    ...
}

Cet exemple illustre la première distinction entre Rust et les autres langages : on écrit future.await plutôt qu’attend futur. Cette syntaxe interagit mieux avec le ? de Rust opérateur pour propager les erreurs, qui sont courantes dans les E/S.

Vous pouvez écrire future.await? pour supporter des fautes et attendre le résultat de beaucoup. De plus, il a l’avantage de rendre la méthode d’enchaînement indolore.

Le terme await ne peut être utilisé que dans le contexte de fonctions asynchrones, et seules les fonctions asynchrones peuvent être attendues.

Les futures de Rust sont laxistes ; par défaut, elles ne feront rien avant que le premier poll soit effectué. Lorsque vous attendez le future, il est sondé.

Par exemple, si vous appelez une fonction qui renvoie un future au début de votre programme mais que vous ne le await pas avant la fin du programme, la requête réelle ne sera pas exécutée avant que vous ne le await.

Exemple:

use std::thread;
use tokio::time::{sleep, Duration};
use futures::future;

#[tokio::main]
async fn main(){
    let mut await_demo = Vec::new();

    for count in 1..=5
    {
        await_demo.push(tokio::spawn(async move{
            println!("Start the thread {count}, id= {:?}", thread::current().id());
            sleep (Duration::from_millis(5000)).await;
            println!("end the thread {count}, id = {:?})", thread::current().id());
        }));
    }
    future::join_all (await_demo).await;
}

Tout d’abord, cinq futures (cinq blocs async) sont créés, chaque future ​​créant un futur sleep et appelant await sur celui-ci. Ces futures existent de manière concurrente.

Chaque bloc affiche l’identifiant du thread avant et après await.

Production:

Standard Output
Start the thread 1, id= ThreadId(2)
Start the thread 3, id= ThreadId(2)
Start the thread 4, id= ThreadId(2)
Start the thread 5, id= ThreadId(2)
Start the thread 2, id= ThreadId(3)
end the thread 2, id = ThreadId(2))
end the thread 3, id = ThreadId(3))
end the thread 1, id = ThreadId(3))
end the thread 4, id = ThreadId(3))
end the thread 5, id = ThreadId(3))