Un atelier Rust · Édition d'ApprentissageA Rust Workshop · Learning Edition

Future & .await, ou le calcul qui ne se lance pas Future & .await, or the computation that doesn't start

Un Future décrit un calcul, il ne le lance pas : non-await, il est inerte. Casser l'analogie avec la promesse JS qui part dès sa création — un bug silencieux fréquent. A Future describes a computation, it doesn't start it: un-awaited, it is inert. Breaking the analogy with the JS promise that fires on creation — a frequent silent bug.

AudienceAudience
Dev maîtrisant possession et threads (Vol 1, Vol 7) — venant souvent d'async JS Dev fluent in ownership and threads (Vol 1, Vol 7) — often from JS async
Format
Self-paced
ChapitresChapters
5
Date
Juin 2026 Jun 2026
≈ 18 min ●●●● AsyncFutureawait

Chapitre 1 en accès libre — la suite (ch. 2 à 5) est réservée. Chapter 1 free to read — the rest (ch. 2–5) is members-only.

01CadrageFraming3 min

La concurrence sans threads : attendre sans bloquer, pas calculer en parallèle.Concurrency without threads: waiting without blocking, not computing in parallel.

Le Vol 7 parlait de parallélisme : faire tourner plusieurs calculs en même temps, sur plusieurs cœurs. L'async répond à un besoin différent, qu'on confond sans cesse avec celui-là : attendre sans bloquer. Pense à un serveur qui tient dix mille connexions, dont chacune dort la plupart du temps en attendant le réseau. Lancer dix mille threads serait un gâchis — chacun coûte sa pile, son changement de contexte. On veut une poignée de threads qui jonglent entre des milliers de tâches en sommeil, reprenant chacune juste quand sa donnée arrive. C'est l'async. En Rust, une async fn ne retourne pas sa valeur : elle retourne un Future, une valeur qui décrit le calcul à mener. Et .await est l'opérateur qui dit « mène ce calcul à terme, mais si tu dois attendre, rends la main pour qu'autre chose avance ».Vol 7 spoke of parallelism: running several computations at once, on several cores. Async answers a different need, constantly confused with that one: waiting without blocking. Picture a server holding ten thousand connections, each asleep most of the time waiting on the network. Spawning ten thousand threads would be waste — each costs its stack, its context switch. You want a handful of threads juggling thousands of sleeping tasks, resuming each just when its data arrives. That's async. In Rust, an async fn doesn't return its value: it returns a Future, a value describing the computation to carry out. And .await is the operator that says 'carry this computation to completion, but if you must wait, yield so something else can advance'.

Concurrence ≠ parallélisme — deux besoins, deux outilsConcurrency ≠ parallelism — two needs, two tools
ASYNC — 1 thread, mille attentesASYNC — 1 thread, a thousand waits
un seul thread jongle entre des tâches qui dormentone thread juggles tasks that sleep
T1
T2
T3
T4

■ actif · ▢ en attente (.await) → la main passe à une autre tâche■ active · ▢ waiting (.await) → control passes to another task

THREADS — N cœurs, N calculsTHREADS — N cores, N computations
chaque cœur mène un calcul de bout en bouteach core runs a computation end to end
C1
C2
C3
C4

■ calcul plein → vrai parallélisme, sur plusieurs cœurs■ full computation → true parallelism, across cores

async fn, .await, et le runtimeasync fn, .await, and the runtime
// async fn ne RETOURNE pas un T — il retourne un Future<Output = T>
async fn charger(url: &str) -> String {
    // … une requête réseau : on ATTEND la réponse sans bloquer le thread
    reponse
}

#[tokio::main]                          // le runtime : il fournit l'exécuteur qui fait tourner les Futures
async fn main() {
    let page = charger("/index").await; // .await : suspend CETTE tâche jusqu'à ce que le Future soit prêt
    println!("{}", page.len());         // … et pendant l'attente, l'exécuteur fait avancer d'autres tâches
}

Trois éléments à repérer. async fn transforme le type de retour : charger ne rend pas un String mais un Future<Output = String>. .await est le point où l'on consomme ce Future — en suspendant la tâche courante le temps de l'attente, sans bloquer le thread. Et #[tokio::main] installe le runtime : la bibliothèque qui fournit l'exécuteur, le moteur qui fait réellement tourner les Future. La std définit le trait Future, mais ne fournit aucun exécuteur — ce choix t'appartient (tokio, async-std…). Sans runtime, un Future n'a personne pour le faire avancer.Three elements to spot. async fn transforms the return type: charger returns not a String but a Future<Output = String>. .await is where you consume that Future — suspending the current task for the wait, without blocking the thread. And #[tokio::main] installs the runtime: the library providing the executor, the engine that actually runs the Futures. The std defines the Future trait, but ships no executor — that choice is yours (tokio, async-std…). Without a runtime, a Future has no one to drive it.

Le réflexe du numéroThe issue's reflex

« Est-ce que j'attends une I/O, ou est-ce que je veux du calcul en parallèle ? » C'est la question qui tranche entre async et threads, et la confondre coûte cher dans les deux sens. Des milliers d'attentes réseau → async, un runtime, une poignée de threads. Du calcul lourd à répartir sur les cœurs → threads (Vol 7), sans runtime async. L'async ne rend aucun calcul plus rapide : il permet seulement de ne pas gaspiller un thread à ne rien faire pendant qu'on attend.'Am I waiting on I/O, or do I want computation in parallel?' That's the question deciding between async and threads, and confusing it costs dearly both ways. Thousands of network waits → async, a runtime, a handful of threads. Heavy computation to spread across cores → threads (Vol 7), no async runtime. Async makes no computation faster: it only lets you not waste a thread doing nothing while you wait.

I/O-bound vs CPU-boundI/O-bound vs CPU-bound

Le vocabulaire qui structure tout le volume. Un programme est I/O-bound quand son temps se passe surtout à attendre quelque chose d'extérieur — réseau, disque, base de données : le processeur est oisif, c'est l'async qui brille. Il est CPU-bound quand son temps se passe à calculer — compression, rendu, simulation : le processeur est saturé, ce sont les threads et les cœurs qu'il faut. La même application peut avoir les deux profils selon l'endroit ; le réflexe est de toujours savoir, à un point donné du code, lequel domine.The vocabulary that structures the whole volume. A program is I/O-bound when its time is spent mostly waiting on something external — network, disk, database: the CPU is idle, async shines. It's CPU-bound when its time is spent computing — compression, rendering, simulation: the CPU is saturated, threads and cores are what you need. The same application can have both profiles depending on the place; the reflex is to always know, at a given point in the code, which dominates.

🔒

La suite est réservée The rest is members-only

Le premier numéro est libre. Débloque tout The Rust Loop — tous les volumes, à vie — pour 5 €, paiement unique. The first issue is free. Unlock all of The Rust Loop — every volume, forever — for €5, one-time.

Retour au kiosqueBack to newsstand