Async/Await — جفت کلمه کلیدی برای نوشتن کد نامتقارن به سبک همزمان است، در Swift از iOS 13 و در Kotlin با کوروتینها قابل دسترسی است. به گزارش Apple Swift Documentation, 2026، Async/Await جایگزین زنجیرههای callback و GCD شده و کد نامتقارن را خطی و خوانا میکند. کلمه کلیدی async تابع را به عنوان نامتقارن علامت گذاری میکند، و await اجرای آن را تا دریافت نتیجه متوقف میکند.
نکات کلیدی
Async/Await — یک ساختار زبانی است که به شما اجازه میدهد کد نامتقارن را به یک شکل خطی مانند کد همزمان بنویسید. در Swift این قابلیت در iOS 13 / macOS 10.15 همراه با چارچوب Swift Concurrency ظاهر شد. در Kotlin، async/await از طریق کتابخانه کوروتین (kotlinx.coroutines) از نسخه 1.3 قابل دسترس است.
پیش از ظهور async/await، کد نامتقارن بر پایه callbackها، GCD یا RxSwift ساخته میشد. زنجیرههای callback تودرتو به callback hell — تودرتوی عمیق که خواندن و اشکالزدایی را دشوار میکند منتهی میشد. Async/Await این مشکل را حل میکند و به توابع نامتقارن اجازه میدهد در نقاط await متوقف شوند و پس از دریافت نتیجه ادامه دهند.
به گزارش گوگل (2025)، استفاده از async/await در Kotlin تعداد خطوط کد نامتقارن را 40–60% در مقایسه با رویکرد callback کاهش میدهد. در Swift، پذیرش Swift Concurrency در سال 2025 به 68% در میان برنامههای منتشرشده رسید. iOS 16 پیشتیبانی از Swift Concurrency را در UIKit، SwiftUI و Foundation اضافه کرد که async/await را به ابزاری استاندارد برای تمام پروژههای جدید Apple تبدیل کرد.
تفاوت کلیدی async/await از تردانهها — توقف بدون بلوک کردن. وقتی تابع به await برسد، متوقف میشود و تردانه فعلی را برای سایر وظایف آزاد میکند. پس از تکمیل عملیات نامتقارن، تابع در همان تردانه یا تردانهای دیگر ادامه مییابد. به این مولتیتاسکینگ همکارانه گفته میشود.
تابع async به یک ماشین حالت — یک اتومات متناهی که حالتهای اجرا را مدیریت میکند کمپیل میشود. در نقطه await، کمپایلر زمینه (متغیرهای محلی، آدرس بازگشت) را ذخیره و کنترل را به runtime انتقال میدهد. وقتی نتیجه آماده شد، runtime زمینه را بازیابی و اجرا را ادامه میدهد.
در Swift، این ماشین حالت در سطح کمپایلر SIL (Swift Intermediate Language) پیادهسازی شده است. در Kotlin — از طریق مکانیسم Continuation Passing Style (CPS): هر تابع suspend یک پارامتر مخفی Continuation دریافت میکند که نتیجه از طریق آن برگردانده میشود. هر دو رویکرد بازیابی ایمن را بدون نشت حافظه تضمین میکنند.
رویکرد callback نیازمند ارسال یک بسته است که پس از تکمیل عملیات فراخوانده میشود. در سه درخواست پیاپی، سه سطح تودرتو با مدیریت خطا در هر سطح ایجاد میشود. Async/Await همان سه درخواست را به سه خط پیاپی با یک بلوک واحد catch تبدیل میکند.
GCD (DispatchQueue) مشکل callback hell را از طریق صفهای serial و DispatchGroup حل میکند، اما پرگویی باقی میماند. برای یک وظیفه ساده — بارگیری user، سپس friends، سپس UI — نیازمند ایجاد صفها، گروهها و بلوکهای notify است. Async/Await همان وظیفه را با سه خط در یک تابع انجام میدهد.
| جنبه | Callback | GCD | Async/Await |
|---|---|---|---|
| تودرتو | عمیق (هرم مرگ) | متوسط (گروهها+notify) | خطی (تخت) |
| مدیریت خطا | در هر callback | دستی | یکپارچه (try/catch) |
| لغو | دستی | محدود | Task.cancel() |
| Thread safety | دستی | از طریق serial queue | از طریق MainActor |
به گزارش Apple WWDC 2024، Swift Concurrency async/await رویکرد توصیهشده برای کد جدید است. GCD برای ادغام با کتابخانههای C و سناریوهای خاص پردازش سطح پایین تردانه باقی مانده است.
Task — واحد اصلی کار نامتقارن در Swift است. Task در زمینه یک actor موجود یا روی هر تردانه ای ایجاد میشود. داخل Task میتوان توابع async را از طریق await فراخواند. TaskGroup به شما اجازه میدهد چندین وظیفه فرعی را به صورت موازی اجرا کرده و نتایج آنها را جمعآوری کنید — معادل DispatchGroup تقویتشده.
Actor — یک نوع مرجعی ایمن در جهت تردانه است که وضعیت خود را در برابر شرایط تسابق دادهها محافظت میکند. کمپایلر تضمین میدهد که دسترسی به ویژگیهای actor فقط از طریق فراخوانیهای async یا داخل انزوای actor ممکن است. Actor جایگزین serial DispatchQueue برای محافظت از وضعیت مشترک تغییرپذیر بدون قفلهای دستی است.
اصل Structured Concurrency میگوید: هر وظیفه نامتقارن یک والد دارد و والد تا تکمیل تمام فرزندانش تکمیل نمیشود. اگر وظیفه A Task { await B() } را اجرا کند، A منتظر B میماند. این از نشت وظایف جلوگیری و چرخه زندگی قابل پیشبینی را تضمین میکند.
در Kotlin، async/await از طریق coroutines — تردانههای سبک زبان پیادهسازی شده است. تابع با کلمه کلیدی suspend علامتگذاری میشود (معادل async در Swift). برای اجرا از launch (بینیاز-و-فراموش) یا async (با نتیجه) استفاده میشود. Await برای دریافت نتیجه از async فراخوانده میشود.
Dispatcher تعیین میکند که کوروتین در چه استخوان تردانهای اجرا شود: Dispatchers.Main برای UI، Dispatchers.IO برای شبکه/دیسک و Dispatchers.Default برای وظایف پردازش شدید میباشد. Structured Concurrency از طریق CoroutineScope تأمین میشود — با لغو scope، تمام کوروتینهای فرعی لغو میشوند.
به گزارش JetBrains (2025)، 97% برنامههای Android در Google Play از kotlinx.coroutines استفاده میکنند و 82% آنها از async/await برای درخواستهای شبکه استفاده میکنند. Coroutines به استاندارد دو فاکتو برای برنامهنویسی نامتقارن در Android تبدیل شدهاند. Kotlin Multiplatform نیز از کوروتینها پشتیبانی میکند و امکان استفاده از کد نامتقارن مشترک را در Android، iOS و طرف سرور فراهم میکند.
برای هر زبان دو نمونه در نظر میگیریم: بارگیری پیاپی دادهها و درخواستهای موازی با TaskGroup یا async/await.
await اجرا را تا دریافت دادههای کاربر متوقف میکند، سپس تا دریافت دوستان. هیچ بسته تودرتویی وجود ندارد.
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)
}
TaskGroup وظایف را به صورت موازی اجرا کرده و نتایج را در یک آرایه جمع میکند. ترتیب نتایج ممکن است با ترتیب اجرا مطابقت نداشته باشد.
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
}
}
توابع suspend میتوانند سایر توابع suspend را فراخوانند. معادل Swift: فراخوانیهای پیاپی.
suspend fun loadProfile(): Profile {
val user = api.fetchUser()
val friends = api.fetchFriends(user.id)
return Profile(user, friends)
}
در Kotlin، همزمانی از طریق coroutineScope با async برای هر درخواست بدست میآید.
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())
}
Task { } فراموششده — تابع نامتقارن را نمیتوان از زمینه همزمان بدون پیچیدن در Task فراخواند. در Swift این با خطای کمپیل همراه است. در Kotlin اجرا از طریق lifecycleScope یا viewModelScope ضروری است. تلاش برای فراخوانی تابع suspend از یک تابع عادی کمپیل نخواهد شد.
لزومی ندارد هر تابعی نامتقارن باشد. وظایف پردازش مطلق بدون I/O از async سودی نمیبرند — بهتر است آنها را در DispatchQueue با .userInitiated QoS اجرا کنید. Async/Await برای عملیاتهای I/O-bound: شبکه، دیسک، انتظار بهینهسازی شده است.
استفاده از .result در تردانه اصلی (انتظار همزمان برای نتیجه تابع async) منجر به بلوک شدن میشود. در Swift، Task.synchronousWait توصیه نمیشود. در Kotlin، runBlocking روی تردانه اصلی یک انتیپاترن است — از lifecycleScope استفاده کنید.
اگر Task در ویژگی کلاس ذخیره نشود، پس از خروج از زمینه لغو میشود. در Swift، Task محدود به زمینه است — چرخه زندگی آن به زمینه ایجادکننده وابسته است. در صورت نیاز به عملیات طولانی، Task را در یک ویژگی ذخیره کنید.
سوالات متداول
Async/Await یک ساختار زبانی است که نیازی به ایجاد صف ندارد. DispatchQueue یک API سیستمی برای مدیریت تردانههاست. Async/await در سطح زبان به state machine و GCD در سطح سیستمعامل به syscall کمپیل میشود.
خیر — await تابع را متوقف میکند، اما تردانه را برای سایر وظایف آزاد میکند. پس از تکمیل عملیات، تابع در هر تردانه موجودی از استخوان ادامه مییابد.
بله — از طریق Task.cancel() در Swift یا Job.cancel() در Kotlin. لغو بر اساس Structured Concurrency به تمام وظایف فرعی سرایت میکند. کد خود علم لغو را از طریق Task.isCancelled یا ensureActive() بررسی میکند.
MainActor یک actor است که ویژگیها و روشهایش همیشه روی تردانه اصلی اجرا میشوند. با علامتگذاری تابع با @MainActor، تضمین میدهید که بهروزرسانیهای UI روی تردانه درست انجام میشوند، جایگزین DispatchQueue.main.async.
Async/Await در Swift (iOS 13+)، Kotlin (از طریق kotlinx.coroutines)، Dart (Flutter)، JavaScript/TypeScript، Python، C#، Rust و Go (از طریق goroutines با شکر نحوی) موجود است.
نتیجهگیری
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید