Async/Await: essens, async-funktioner och arbete med await

Författare: IT Sectr Publicerad: 2026-03-16 Lästid: 8 min

Async/Await är ett par nyckelord för att skriva asynkron kod i synkron stil, tillgängligt i Swift från iOS 13 och i Kotlin med coroutines. Enligt Apple Swift Documentation, 2026 ersätter Async/Await callback-kedjor och GCD, vilket gör asynkron kod linjär och läsbar. Nyckelordet async markerar en funktion som asynkron, och await pausar dess körning tills resultatet erhålls.

Huvudpunkter

  • Async/Await — syntaktiskt socker för asynkron kod utan nästlade callbacks
  • async markerar en funktion som asynkron och pausbar
  • await pausar funktionens körning tills den asynkrona operationen är klar
  • Task i Swift skapar en ny asynkron arbetsenhet med kontext
  • Structured Concurrency garanterar att alla underordnade uppgifter slutförs innan den överordnade

Vad är Async/Await och asynkron programmering

Async/Await är en språkkonstruktion som gör det möjligt att skriva asynkron kod linjärt precis som synkron kod. I Swift finns den från iOS 13 / macOS 10.15 tillsammans med Swift Concurrency-ramverket. I Kotlin är async/await tillgängligt via coroutine-biblioteket (kotlinx.coroutines) från version 1.3.

Före async/await byggdes asynkron kod med callbacks, GCD eller RxSwift. Nästlade callback-kedjor ledde till callback hell — djup nästling som försvårar läsning och felsökning. Async/Await löser detta problem genom att låta asynkrona funktioner "pausa" vid await-punkter och återupptas efter att resultatet erhållits.

Enligt Google (2025) minskar användningen av async/await i Kotlin antalet rader asynkron kod med 40–60% jämfört med callback-metoden. I Swift nådde adoptionen av Swift Concurrency 68% bland publicerade appar under 2025. iOS 16 lade till stöd för Swift Concurrency i UIKit, SwiftUI och Foundation, vilket gjorde async/await till standardverktyget för alla nya Apple-projekt.

Arbetsprincip: pausbara funktioner

Den viktigaste skillnaden mellan async/await och trådar är paus utan blockering. När en funktion stöter på await pausas den och frigör den aktuella tråden för andra uppgifter. Efter att den asynkrona operationen slutförts återupptas funktionen på samma eller en annan tråd. Detta kallas cooperative multitasking.

Hur Async/Await fungerar: paus och återupptagning

En async-funktion kompileras till en state machine — en finit tillståndsmaskin som hanterar körningstillstånd. Vid await-punkten sparar kompilatorn kontexten (lokala variabler, returadress) och överlämnar kontrollen till runtime. När resultatet är klart återställer runtime kontexten och fortsätter körningen.

I Swift är denna tillståndsmaskin implementerad på kompilatornivå via SIL (Swift Intermediate Language). I Kotlin — via Continuation Passing Style (CPS)-mekanismen: varje suspend-funktion tar emot en dold parameter Continuation som returnerar resultatet. Båda metoderna garanterar säker återupptagning utan minnesläckor.

  • Swift — kompilatorn översätter async-funktioner till SIL med en runAsync coroutine frame
  • Kotlin — varje suspend-funktion tar emot en Continuation och delegerar körning till dispatchern
  • Båda språken — frigör tråden vid await, blockerar den inte under väntan
  • Undantag — hanteras via standardmekanismer (throws / try-catch)

Async/Await vs Callbacks och GCD: jämförelse av metoder

Callback-metoden kräver att en closure skickas som anropas efter att operationen slutförts. Vid tre sekventiella förfrågningar uppstår tre nivåer av nästling med felhantering på varje nivå. Async/Await förvandlar samma tre förfrågningar till tre sekventiella rader med ett enda catch-block.

GCD (DispatchQueue) löser callback-hell-problemet via seriella köer och DispatchGroup, men förblir omständligt. För en enkel uppgift — ladda user, sedan friends, sedan UI — krävs skapande av köer, grupper och notify-block. Async/Await utför samma uppgift med tre rader i en enda funktion.

AspektCallbackGCDAsync/Await
NästlingDjup (pyramid of doom)Medel (grupper+notify)Linjär (flat)
FelhanteringPer-callbackManuellEnhetlig (try/catch)
AvbrytningManuellBegränsadTask.cancel()
TrådsäkerhetManuellVia serial queueVia MainActor

Enligt Apple WWDC 2024 är Swift Concurrency async/await den rekommenderade metoden för ny kod. GCD används fortfarande för integration med C-bibliotek och specifika lågnivåscenarier för trådhantering.

Swift Concurrency: Task, TaskGroup och Actor

Task är den grundläggande enheten för asynkront arbete i Swift. En Task skapas i kontexten av en befintlig actor eller på en godtycklig tråd. Inuti en Task kan async-funktioner anropas via await. TaskGroup gör det möjligt att köra flera underordnade uppgifter parallellt och samla deras resultat — en kraftfullare version av DispatchGroup.

Actor är en trådsäker referenstyp som skyddar sitt tillstånd från race conditions. Kompilatorn garanterar att åtkomst till en actors egenskaper endast är möjlig via async-anrop eller inom actor-isolering. Actor ersätter serial DispatchQueue för att skydda delat muterbart tillstånd utan manuella lås.

Structured Concurrency

Principen för Structured Concurrency säger: varje asynkron uppgift har en förälder, och föräldern slutförs inte förrän alla dess barn är klara. Om uppgift A kör Task { await B() }, väntar A på B. Detta förhindrar uppgiftsläckor och säkerställer en förutsägbar livscykel.

Async/Await i Kotlin med coroutines

I Kotlin är async/await implementerat via coroutines — språkets lättvikts-trådar. En funktion markeras med nyckelordet suspend (analogt med Swift's async). För körning används launch (fire-and-forget) eller async (med resultat). Await anropas för att hämta resultatet från async.

Dispatcher bestämmer på vilken trådpool coroutinen körs: Dispatchers.Main för UI, Dispatchers.IO för nätverk/disk och Dispatchers.Default för CPU-intensiva uppgifter. Structured Concurrency garanteras via CoroutineScope — när scopet avbryts avbryts alla underordnade coroutines.

Enligt JetBrains (2025) använder 97% av Android-apparna i Google Play kotlinx.coroutines, och 82% av dem använder async/await för nätverksförfrågningar. Coroutines har blivit de facto-standarden för asynkron programmering i Android. Kotlin Multiplatform stöder också coroutines, vilket möjliggör delad asynkron kod på Android, iOS och serversidan.

Kodexempel med Async/Await i Swift och Kotlin

Låt oss titta på två exempel för varje språk: sekventiell dataladdning och parallella förfrågningar med TaskGroup eller async/await.

Swift: sekventiella async-anrop

await pausar körningen tills användardata har hämtats, sedan tills vänner har hämtats. Inga nästlade closures.

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: parallella förfrågningar med TaskGroup

TaskGroup kör uppgifter parallellt och samlar resultaten i en array. Ordningen på resultaten kan skilja sig från startordningen.

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: sekventiellt anrop med async/await

suspend-funktioner kan anropa andra suspend-funktioner. Analogt med Swift: sekventiella anrop.

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

Kotlin: parallella förfrågningar med async/await

I Kotlin uppnås parallellism via coroutineScope med async för varje förfrågan.

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())
}

Vanliga misstag och begränsningar med Async/Await

Glömd Task { } — en asynkron funktion kan inte anropas från en synkron kontext utan att vara inslagen i en Task. I Swift resulterar detta i ett kompileringsfel. I Kotlin krävs körning via lifecycleScope eller viewModelScope. Att anropa en suspend-funktion från en vanlig funktion kompileras inte.

Överdriven användning av async utan behov

Inte varje funktion behöver göras asynkron. CPU-intensiva uppgifter utan I/O drar inte nytta av async — de körs bättre på en DispatchQueue med .userInitiated QoS. Async/Await är optimerat för I/O-bundna operationer: nätverk, disk, väntan.

Blockering av huvudtråden via .result

Användning av .result på huvudtråden (synkron väntan på resultat från en async-funktion) leder till blockering. I Swift rekommenderas inte Task.synchronousWait av Apple. I Kotlin är runBlocking på huvudtråden ett antipattern — använd lifecycleScope.

Uppgiftsläcka vid avbrytning

Om en Task inte sparas i en klassegenskap avbryts den efter att kontexten lämnats. I Swift är Task scoped — dess livscykel är bunden till den skapande kontexten. Spara Task i en egenskap om en långvarig operation behövs.

Vanliga frågor

Vad är skillnaden mellan async/await och DispatchQueue?

Async/Await är en språkkonstruktion som inte kräver skapande av köer. DispatchQueue är ett system-API för trådhantering. Async/await kompileras till en state machine på språknivå, GCD till ett syscall på OS-nivå.

Blockerar await tråden?

Nej — await pausar funktionen men frigör tråden för andra uppgifter. Efter att operationen slutförts återupptas funktionen på en tillgänglig tråd från poolen.

Kan en asynkron uppgift avbrytas?

Ja — via Task.cancel() i Swift eller Job.cancel() i Kotlin. Avbrytning sprids till alla underordnade uppgifter enligt Structured Concurrency. Koden kontrollerar avbrytningsflaggan via Task.isCancelled eller ensureActive().

Vad är MainActor i Swift?

MainActor är en actor vars egenskaper och metoder alltid körs på huvudtråden. Genom att markera en funktion med @MainActor garanterar du att UI-uppdateringar sker på rätt tråd, istället för DispatchQueue.main.async.

I vilka språk finns async/await?

Async/Await finns i Swift (iOS 13+), Kotlin (via kotlinx.coroutines), Dart (Flutter), JavaScript/TypeScript, Python, C#, Rust och Go (via goroutines med syntaktiskt socker).

Sammanfattning

  • Async/Await — språkkonstruktion för linjär asynkron kod utan callback hell
  • Swift Concurrency tillhandahåller Task, TaskGroup, Actor och Structured Concurrency
  • Kotlin coroutines använder suspend-funktioner, Dispatchers och coroutine-scopes
  • Paus utan blockering — den viktigaste skillnaden mellan async/await och trådar/köer
  • Structured Concurrency garanterar slutförande av alla underordnade uppgifter före den överordnade
  • Async/Await vs GCD — förstnämnda att föredra för ny kod, det andra för legacy och lågnivå
  • MainActor i Swift och Dispatchers.Main i Kotlin skyddar UI-tråden från bakgrundsoperationer

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också