Ответ
Async/await — это модель асинхронного программирования в Swift, позволяющая писать линейный, легко читаемый код вместо использования completion handlers или цепочек Future/Promise.
Основные принципы:
async— маркирует функцию как асинхронную. Такая функция может быть приостановлена (suspended).await— указывает точку приостановки, в которой выполнение может быть передано другим задачам, пока ожидается результат асинхронного вызова.- Structured Concurrency: Асинхронные задачи выполняются в структурированной иерархии, что упрощает управление жизненным циклом и отмену.
Базовый пример:
// 1. Объявление асинхронной функции
func fetchUserData(from url: URL) async throws -> User {
let (data, _) = try await URLSession.shared.data(from: url) // 'await' — точка приостановки
return try JSONDecoder().decode(User.self, from: data)
}
// 2. Вызов в асинхронном контексте (Task)
Task {
do {
let user = try await fetchUserData(from: someURL)
await MainActor.run { // Возврат в главный поток для UI-обновлений
self.usernameLabel.text = user.name
}
} catch {
print("Fetch failed: (error)")
}
}
Ключевые преимущества:
- Читаемость: Код выглядит как синхронный, нет "адской пирамиды" из замыканий.
- Безопасность: Компилятор контролирует правильное использование асинхронного контекста.
- Интеграция с ошибками: Полная поддержка
try/catch. - Отмена задач: Встроенная поддержка через
Task.checkCancellation()иTask.isCancelled.
Важное ограничение: Функции с await можно вызывать только из асинхронного контекста (другой async-функции или блока Task).
Ответ 18+ 🔞
Ну вот, смотри, опять эти ваши асинхронные штуки. Раньше, блядь, жили спокойно — completion handlers, цепочки промисов, адская пирамида из замыканий, в рот меня чих-пых! Код читаешь — глаза сломать можно, будто мартышлюшка на клавиатуре плясала.
А теперь, ёпта, придумали async/await. И знаешь что? Овердохуища удобно, ей-богу!
Суть, если по-простому:
async— это как бирка на функцию: «Эй, чувак, я могу зависнуть, не торопи меня, блядь!».await— это точка, где ты говоришь: «Ладно, я подожду тут, а ты, система, иди пока другие дела поделай, не стой столбом».- Structured Concurrency — это чтоб задачи, как дети малые, по иерархии бегали, а не как угорелые по всему процессу. Упрощает жизнь — отменить их или отследить проще.
Смотри, как теперь красивше:
// 1. Вот тебе асинхронная функция. Видишь `async`? Всё, она особенная.
func fetchUserData(from url: URL) async throws -> User {
// Ждём данные с сервака. `await` — тут мы можем приостановиться.
let (data, _) = try await URLSession.shared.data(from: url)
// Декодируем и валим обратно.
return try JSONDecoder().decode(User.self, from: data)
}
// 2. А вызываем вот так, в Task'е.
Task {
do {
// Красота же? Прям как синхронный код! Никаких лесенок из замыканий!
let user = try await fetchUserData(from: someURL)
// Обновляем интерфейс, возвращаемся на главный поток.
await MainActor.run {
self.usernameLabel.text = user.name
}
} catch {
// А ошибки ловим как у нормальных людей, try/catch.
print("Fetch failed: (error)") // Ну, тут понятно, всё просралось.
}
}
И чем это, блядь, хорошо?
- Читаемость — нихуя не надо глаза ломать, код линейный.
- Безопасность — компилятор, хитрая жопа, сам следит, чтоб ты по правилам играл.
- Ошибки — наконец-то можно
try/catchиспользовать, а не по колбэкам их раскидывать. - Отмена — встроенная, можно проверить, не отменили ли тебя:
Task.checkCancellation().
Но есть, сука, подвох: Функцию с await вызвать можно только из другого асинхронного контекста. То есть либо из такой же async-функции, либо из блока Task. Иначе компилятор тебе такое ебало нарисует — мама не горюй.