Async/Await : essence, fonctions async et travail avec await

Auteur : IT Sectr Publié le : 2026-03-16 Temps de lecture : 8 min

Async/Await est une paire de mots-clés pour écrire du code asynchrone dans un style synchrone, disponible en Swift depuis iOS 13 et en Kotlin avec les coroutines. Selon Apple Swift Documentation, 2026, Async/Await remplace les chaînes de callbacks et GCD, rendant le code asynchrone linéaire et lisible. Le mot-clé async marque une fonction comme asynchrone, et await suspend son exécution jusqu'à la réception du résultat.

Points Clés

  • Async/Await est du sucre syntaxique pour du code asynchrone sans callbacks imbriqués
  • async marque une fonction comme asynchrone et suspendable
  • await suspend l'exécution de la fonction jusqu'à la fin de l'opération asynchrone
  • Task dans Swift crée une nouvelle unité de travail asynchrone avec contexte
  • Structured Concurrency garantit que toutes les tâches enfants se terminent avant la parent

Qu'est-ce qu'Async/Await et la programmation asynchrone ?

Async/Await est une construction de langage qui permet d'écrire du code asynchrone aussi linéairement que le code synchrone. Dans Swift, il est apparu dans iOS 13 / macOS 10.15 avec le framework Swift Concurrency. Dans Kotlin, async/await est disponible via la bibliothèque de coroutines (kotlinx.coroutines) depuis la version 1.3.

Avant async/await, le code asynchrone était construit sur des callbacks, GCD ou RxSwift. Les chaînes de callbacks imbriqués menaient à l'enfer des callbacks — une imbrication profonde qui complique la lecture et le débogage. Async/Await résout ce problème en permettant aux fonctions asynchrones de « suspendre » aux points await et de reprendre après réception du résultat.

Selon Google (2025), l'utilisation d'async/await dans Kotlin réduit le nombre de lignes de code asynchrone de 40 à 60 % par rapport à l'approche par callbacks. Dans Swift, l'adoption de Swift Concurrency a atteint 68 % parmi les applications publiées en 2025. iOS 16 a ajouté la prise en charge de Swift Concurrency dans UIKit, SwiftUI et Foundation, faisant d'async/await l'outil standard pour tous les nouveaux projets Apple.

Principe de fonctionnement : fonctions suspendables

La principale différence entre async/await et les threads est la suspension sans blocage. Lorsqu'une fonction rencontre await, elle se suspend, libérant le thread actuel pour d'autres tâches. Une fois l'opération asynchrone terminée, la fonction reprend sur le même thread ou sur un autre. C'est ce qu'on appelle le multitâche coopératif.

Comment fonctionne Async/Await : suspension et reprise

Une fonction async est compilée en une machine d'états — un automate fini qui gère les états d'exécution. Au point await, le compilateur sauvegarde le contexte (variables locales, adresse de retour) et donne le contrôle au runtime. Lorsque le résultat est prêt, le runtime restaure le contexte et continue l'exécution.

Dans Swift, cette machine d'états est implémentée au niveau du compilateur SIL (Swift Intermediate Language). Dans Kotlin, le mécanisme Continuation Passing Style (CPS) est utilisé : chaque fonction suspend accepte un paramètre Continuation caché par lequel le résultat est retourné. Les deux approches garantissent une reprise sécurisée sans fuites mémoire.

  • Swift — le compilateur traduit la fonction async en SIL avec un runAsync coroutine frame
  • Kotlin — chaque fonction suspend reçoit un Continuation et délègue l'exécution au dispatcher
  • Les deux langages — libèrent le thread à await, sans le bloquer pendant l'attente
  • Exceptions — propagées via les mécanismes standards (throws / try-catch)

Async/Await vs Callbacks et GCD : comparaison des approches

L'approche par callbacks nécessite de passer une closure qui est appelée après la fin de l'opération. Avec trois requêtes séquentielles, on obtient trois niveaux d'imbrication avec gestion d'erreurs à chaque niveau. Async/Await transforme ces trois mêmes requêtes en trois lignes séquentielles avec un seul bloc catch.

GCD (DispatchQueue) résout l'enfer des callbacks via des files d'attente séries et DispatchGroup, mais reste verbeux. Pour une tâche simple — charger un utilisateur, puis les amis, puis l'interface — il faut créer des files, des groupes et des blocs notify. Async/Await effectue la même tâche avec trois lignes dans une seule fonction.

AspectCallbackGCDAsync/Await
ImbricationProfonde (pyramide de la perdition)Moyenne (groupes+notify)Linéaire (plate)
Gestion des erreursPar callbackManuelleUnifiée (try/catch)
AnnulationManuelleLimitéeTask.cancel()
Sécurité des threadsManuelleVia file sérieVia MainActor

Selon Apple WWDC 2024, Swift Concurrency async/await est l'approche recommandée pour le nouveau code. GCD reste pour l'intégration avec les bibliothèques C et les scénarios spécifiques de bas niveau de gestion des threads.

Swift Concurrency : Task, TaskGroup et Actor

Task est l'unité de base du travail asynchrone dans Swift. Une Task est créée dans le contexte d'un acteur existant ou sur un thread arbitraire. À l'intérieur d'une Task, on peut appeler des fonctions async via await. TaskGroup permet de lancer plusieurs tâches enfants en parallèle et de collecter leurs résultats — un analogue de DispatchGroup amélioré.

Actor est un type de référence thread-safe qui protège son état des courses de données. Le compilateur garantit que l'accès aux propriétés de l'acteur n'est possible que par des appels async ou dans l'isolement de l'acteur. Actor remplace la DispatchQueue série pour protéger l'état mutable partagé sans verrous manuels.

Structured Concurrency

Le principe de Structured Concurrency énonce : chaque tâche asynchrone a un parent, et le parent ne se termine pas tant que tous ses enfants ne sont pas terminés. Si la tâche A lance Task { await B() }, alors A attend B. Cela empêche les fuites de tâches et garantit un cycle de vie prévisible.

Async/Await en Kotlin avec les coroutines

Dans Kotlin, async/await est implémenté via les coroutines — des threads légers du langage. Une fonction est marquée avec le mot-clé suspend (analogue à async de Swift). Pour lancer, on utilise launch (fire-and-forget) ou async (avec résultat). Await est appelé pour obtenir le résultat d'async.

Dispatcher détermine sur quel pool de threads la coroutine s'exécute : Dispatchers.Main pour l'interface, Dispatchers.IO pour le réseau/disque et Dispatchers.Default pour les tâches intensives en CPU. Structured Concurrency est garantie via CoroutineScope — lorsque le scope est annulé, toutes les coroutines enfants sont annulées.

Selon JetBrains (2025), 97 % des applications Android sur Google Play utilisent kotlinx.coroutines, et 82 % d'entre elles utilisent async/await pour les requêtes réseau. Les coroutines sont devenues le standard de facto pour la programmation asynchrone sur Android. Kotlin Multiplatform prend également en charge les coroutines, permettant d'utiliser du code asynchrone partagé sur Android, iOS et le serveur.

Exemples de code avec Async/Await en Swift et Kotlin

Regardons deux exemples pour chaque langage : chargement séquentiel de données et requêtes parallèles avec TaskGroup ou async/await.

Swift : Appels async séquentiels

await suspend l'exécution jusqu'à la réception des données utilisateur, puis jusqu'à la réception des amis. Aucune closure imbriquée.

swift
func loadProfile() async throws -> Profile {
    let user = try await api.fetchUser()
    let friends = try await api.fetchFriends(for: user.id)
    return Profile(user: user, friends: friends)
}

Swift : Requêtes parallèles avec TaskGroup

TaskGroup lance des tâches en parallèle et collecte les résultats dans un tableau. L'ordre des résultats peut ne pas correspondre à l'ordre de lancement.

swift
func loadParallel() async throws -> [String] {
    await withThrowingTaskGroup(of: String.self) { group in
        group.addTask { try await api.fetchName() }
        group.addTask { try await api.fetchEmail() }
        group.addTask { try await api.fetchAvatar() }
        var results = [String]()
        for try await value in group { results.append(value) }
        return results
    }
}

Kotlin : Appel séquentiel avec async/await

Les fonctions suspend peuvent appeler d'autres fonctions suspend. Analogue à Swift : appels séquentiels.

kotlin
suspend fun loadProfile(): Profile {
    val user = api.fetchUser()
    val friends = api.fetchFriends(user.id)
    return Profile(user, friends)
}

Kotlin : Requêtes parallèles avec async/await

Dans Kotlin, le parallélisme est réalisé via coroutineScope avec async pour chaque requête.

kotlin
suspend fun loadParallel(): List<String> = coroutineScope {
    val name = async { api.fetchName() }
    val email = async { api.fetchEmail() }
    val avatar = async { api.fetchAvatar() }
    listOf(name.await(), email.await(), avatar.await())
}

Erreurs courantes et limites d'Async/Await

Task { } oubliée — une fonction async ne peut pas être appelée depuis un contexte synchrone sans être enveloppée dans une Task. Dans Swift, cela génère une erreur de compilation. Dans Kotlin, cela nécessite un lancement via lifecycleScope ou viewModelScope. Essayer d'appeler une fonction suspend depuis une fonction normale ne compilera pas.

Utilisation excessive d'async sans nécessité

Toutes les fonctions n'ont pas besoin d'être asynchrones. Les tâches intensives en CPU sans E/S ne bénéficient pas d'async — il est préférable de les exécuter sur DispatchQueue avec QoS .userInitiated. Async/Await est optimisé pour les opérations liées aux E/S : réseau, disque, attente.

Blocage du thread principal via .result

Utiliser .result sur le thread principal (attente synchrone du résultat d'une fonction async) entraîne un blocage. Dans Swift, Task.synchronousWait n'est pas recommandé par Apple. Dans Kotlin, runBlocking sur le thread principal est un anti-patron — utilisez lifecycleScope.

Fuite de Task lors de l'annulation

Si une Task n'est pas stockée dans une propriété de classe, après avoir quitté le contexte, elle est annulée. Dans Swift, Task est limitée par portée — son cycle de vie est lié au contexte créateur. Stockez la Task dans une propriété si vous avez besoin d'une opération de longue durée.

Foire Aux Questions

En quoi async/await diffère-t-il de DispatchQueue ?

Async/Await est une construction de langage qui ne nécessite pas de créer des files d'attente. DispatchQueue est une API système pour gérer les threads. Async/await est compilé en une machine d'états au niveau du langage, GCD — en syscalls au niveau de l'OS.

Est-ce que await bloque le thread ?

Non — await suspend la fonction mais libère le thread pour d'autres tâches. Une fois l'opération terminée, la fonction reprend sur n'importe quel thread disponible du pool.

Peut-on annuler une tâche async ?

Oui — via Task.cancel() dans Swift ou Job.cancel() dans Kotlin. L'annulation se propage à toutes les tâches enfants selon Structured Concurrency. Le code vérifie le drapeau d'annulation via Task.isCancelled ou ensureActive().

Qu'est-ce que MainActor dans Swift ?

MainActor est un acteur dont les propriétés et méthodes s'exécutent toujours sur le thread principal. En marquant une fonction avec @MainActor, vous garantissez que les mises à jour de l'interface utilisateur se produisent sur le bon thread, remplaçant DispatchQueue.main.async.

Dans quels langages existe async/await ?

Async/Await est disponible dans Swift (iOS 13+), Kotlin (via kotlinx.coroutines), Dart (Flutter), JavaScript/TypeScript, Python, C#, Rust et Go (via goroutines avec sucre syntaxique).

Résumé

  • Async/Await est une construction de langage pour du code asynchrone linéaire sans enfer des callbacks
  • Swift Concurrency fournit Task, TaskGroup, Actor et Structured Concurrency
  • Les coroutines Kotlin utilisent des fonctions suspend, Dispatchers et des scopes de coroutines
  • La suspension sans blocage est la principale différence d'async/await avec les threads et les files
  • Structured Concurrency garantit que toutes les tâches enfants se terminent avant la parent
  • Async/Await vs GCD — le premier est préférable pour le nouveau code, le second pour l'ancien et le bas niveau
  • MainActor dans Swift et Dispatchers.Main dans Kotlin protègent le thread UI des opérations d'arrière-plan

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi