Заглядываем внутрь async let
Каждая задача, созднанная с помощью async let
является структурированной.
Жизненный цикл async let
- Перед созданием задачи, компилятор выделяет большое фиксированное кол-во памяти. Вместе с этим устанавливаются внутренние флаги, записи о дочерних задачах и контекст.
- Инициализация задачи и её прикрепление к родительской задачи.
- Приостановка и возобновление. Сама по себе
async let
не является точкой приостановки, но при обращение кasync let
задаче с помощью ключевого словаawait
, текущая задача приостанавливает свое выполнение и сохраняет состояние. - Обработка ошибок. Задача может вернуть ошибку вместо результата.
- Отмена задачи при выходе из области видимости.
- Удаление записей о дочерних задачах.
- Освобождение памяти для дочерних задач и самой
async let
задачи.
При создании задачи с помощью async let
компилятор определяет является ли она структурированной или не структурированной с помощью вспомогательных методов:
static inline bool taskIsStructured(JobFlags jobFlags) {
return jobFlags.task_isAsyncLetTask() || jobFlags.task_isGroupChildTask();
}
static inline bool taskIsUnstructured(TaskCreateFlags createFlags, JobFlags jobFlags) {
return !taskIsStructured(jobFlags) && !createFlags.isInlineTask();
}
static inline bool taskIsDetached(TaskCreateFlags createFlags, JobFlags jobFlags) {
return taskIsUnstructured(createFlags, jobFlags) && !createFlags.copyTaskLocals();
}
На примере
Посмотрим на самом маленьком примере:
func makeNames() async -> [String] {
["Siri", "ChatGPT", "Vertex"]
}
async let names: [String] = makeNames() // 1
await names // 2
// Пример с настоящими данными
async let data: Data = URLSession.shared.data(from: .init(string: "https://speedtest.selectel.ru/10MB")!).0
let result = try await data
print("Data size: \(result.count)")
// или более короткой синтаксис
// print("Data size: \(try await data)")
Под первым комментарием // 1
мы создаем задачу с помощью async let
синтаксиса. Важно понять, что в этом случае задача не приостанавливается, поскольку ключевое слово await
отсутствует.
Только во второй комментарии мы указываем ключевое слово await
, с помощью которого задача приостанавливается и возвращает результат.
Чуть ниже я указал пример с настоящими данными (10MB), попробуйте запустить его.