Continuations для взаимодействия асинхронных задач с синхронным кодом

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

В Swift были представлены новые функции, которые помогают нам адаптировать старые API в стиле completionhandler к современному асинхронному коду.

Например, эта функция возвращает свои значения асинхронно, используя обработчик завершения:

import Foundation

func fetchLatestNews(completion: @escaping ([String]) -> Void) {
    DispatchQueue.main.async {
        completion(["Swift 5.5 release", "Apple acquires Apollo"])
    }
}

Если бы мы хотели использовать ее с помощью async/await, мы могли бы переписать функцию, но есть различные причины, по которым это может оказаться невозможным – например, она может быть взята из внешней библиотеки.

Continuations позволяют нам создать обертку над обработчиком завершения (completion handler) и асинхронными функциями, чтобы мы могли обернуть старый код в более современный API. Например, функция withCheckedContinuation() создает новое continuation, которое может запускать любой код, который мы хотим, а затем вызывает resume(returning:), чтобы отправить значение обратно, даже если это часть обработчика завершения (completion handler).

Итак, мы можем создать вторую асинхронную функцию fetchLatestNews(), обернутую вокруг старой функции с completionhandler:

func fetchLatestNews() async -> [String] {
    await withCheckedContinuation { continuation in
        fetchLatestNews { items in
            continuation.resume(returning: items)
        }
    }
}

Теперь мы можем получить нашу исходную функциональность в асинхронной функции, например, следующим образом:

func printNews() async {
    let items = await fetchLatestNews()

    for item in items {
        print(item)
    }
}

Термин “checked” continuation означает, что Swift выполняет проверки во время выполнения от нашего имени: вызываем ли мы resume() один и только один раз? Это важно, потому что, если мы никогда не вызовем resume(), произойдет утечка ресурсов, но если мы вызовем его дважды, то, скорее всего, столкнемся с проблемами.

Важно: Мы должны вызывать resume() ровно один раз.

Поскольку проверка наших continuations сопряжена с затратами и производительностью во время выполнения, Swift также предоставляет функцию withUnsafeContinuation(), которая работает точно так же, за исключением того, что не выполняет проверки во время выполнения. Это означает, что Swift не предупредит нас, если мы забудем вызвать resume(), и если мы вызовем его дважды, то поведение будет не определено.

Поскольку эти две функции вызываются одинаковым образом, мы можем легко переключаться между ними. Кажется наиболее вероятным, что люди будут использовать withCheckedContinuation() при написании своих функций, поэтому Swift будет выдавать предупреждения и даже вызывать сбои, если continuations используются неправильно, но некоторые могут затем переключиться на withUnsafeContinuation(), если для них критичны затраты и производительность во время выполнения checked continuations.

Источник: https://habr.com/ru/articles/797735/


Интересные статьи

Интересные статьи

Какое-то время назад мы столкнулись с проблемой: сроки нашей разработки и темпы реализации начали сильно стопориться. При запуске фичей команда сталкивалась с отсутствием прозрачности при отображении ...
Представьте айсберг. На его верхушке знание о том, что руководителю нужно уметь делегировать задачи. А вот как именно это делать и почему бывает очень больно — скрыто в темных водах. Под катом разби...
Меня всегда волновал вопрос: можно ли писать код единственно правильным образом. В данной статье я через противоречие доказываю, что при изменении бизнес требований написать код так, чтоб...
Последние 6 лет я работаю экспертом по информационной безопасности в Одноклассниках и отвечаю за безопасность приложений. Мой доклад сегодня — о механизмах межпроцессного взаимодействия...
У специалистов по обработке и анализу данных есть множество средств для создания классификационных моделей. Один из самых популярных и надёжных методов разработки таких моделей заключается в испо...