← Назад к вопросам

Приведи пример использования async/await

1.7 Middle🔥 201 комментариев
#Многопоточность и асинхронность

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Использование async/await в Swift (Concurrency)

async/await — это ключевая модель асинхронного программирования в Swift, представленная в Swift 5.5. Она позволяет писать асинхронный код, который выглядит и читается как синхронный, избегая сложностей с callback'ами и completion handlers. Основная идея: функции, помеченные как async, могут "приостанавливать" выполнение, ожидая результат, без блокировки потока, а await используется для вызова таких функций.

Основные примеры использования

1. Базовый пример: асинхронная функция загрузки данных

import Foundation

// Асинхронная функция, которая загружает данные из URL
func fetchData(from urlString: String) async throws -> Data {
    guard let url = URL(string: urlString) else {
        throw URLError(.badURL)
    }
    
    // Используем await для вызова асинхронного метода data(from:)
    let (data, _) = try await URLSession.shared.data(from: url)
    return data
}

// Использование в другой асинхронной функции или Task
func processData() async {
    do {
        let data = try await fetchData(from: "https://api.example.com/data")
        print("Данные получены: \(data.count) байт")
        // Дальнейшая обработка...
    } catch {
        print("Ошибка загрузки: \(error)")
    }
}

2. Использование в Task для запуска из синхронного контекста

Асинхронные функции должны вызываться из асинхронного контекста. Для запуска из обычного (синхронного) метода используется Task.

class ViewModel {
    func loadData() {
        // Создаем Task для выполнения асинхронной работы
        Task {
            do {
                let data = try await fetchData(from: "https://api.example.com/data")
                await MainActor.run {
                    // Обновляем UI на главном потоке
                    self.updateUI(with: data)
                }
            } catch {
                print("Ошибка: \(error)")
            }
        }
    }
    
    @MainActor
    private func updateUI(with data: Data) {
        // Обновление интерфейса
    }
}

3. Параллельное выполнение с async let

Для параллельного выполнения нескольких асинхронных операций используется async let.

func fetchMultipleResources() async throws -> (Data, Data) {
    // Запускаем две загрузки параллельно
    async let firstData = fetchData(from: "https://api.example.com/resource1")
    async let secondData = fetchData(from: "https://api.example.com/resource2")
    
    // Ожидаем результаты обеих операций
    return (try await firstData, try await secondData)
}

4. Асинхронные последовательности (AsyncSequence)

Swift поддерживает асинхронные последовательности для обработки потоков данных.

func monitorDownloads() async {
    let urls = ["https://api.example.com/file1", "https://api.example.com/file2"]
    
    // Используем async for-in для обработки каждого элемента
    for try await data in asyncDownloadSequence(urls: urls) {
        print("Загружен файл размером: \(data.count) байт")
    }
}

// Пример асинхронной последовательности
func asyncDownloadSequence(urls: [String]) -> AsyncThrowingStream<Data, Error> {
    AsyncThrowingStream { continuation in
        Task {
            for url in urls {
                do {
                    let data = try await fetchData(from: url)
                    continuation.yield(data)
                } catch {
                    continuation.finish(throwing: error)
                    break
                }
            }
            continuation.finish()
        }
    }
}

5. Практический пример: кэширование с асинхронным доступом

actor ImageCache {
    private var cache: [String: Data] = []
    
    // actor обеспечивает безопасность доступа из разных потоков
    func getImage(for key: String) async -> Data? {
        return cache[key]
    }
    
    func setImage(_ data: Data, for key: String) async {
        cache[key] = data
    }
}

class ImageLoader {
    private let cache = ImageCache()
    
    func loadImage(urlString: String) async throws -> Data {
        // Проверяем кэш
        if let cached = await cache.getImage(for: urlString) {
            return cached
        }
        
        // Загружаем если нет в кэше
        let data = try await fetchData(from: urlString)
        
        // Сохраняем в кэш
        await cache.setImage(data, for: urlString)
        return data
    }
}

Ключевые преимущества async/await

  • Упрощение кода: Замена цепочек completion handlers на линейный код.
  • Обработка ошибок: Использование стандартного механизма try/catch вместо отдельных обработчиков ошибок.
  • Безопасность потоков: actor предотвращает гонки данных.
  • Параллелизм: async let и TaskGroup для эффективного параллельного выполнения.
  • Интеграция с существующим API: Многие стандартные библиотеки (URLSession, FileManager) получили async версии методов.

async/await фундаментально меняет подход к асинхронному программированию в Swift, делая код более чистым, безопасным и эффективным.

Приведи пример использования async/await | PrepBro