Async/await

Async/await — это синтаксическая конструкция, реализуемая во многих языках программирования, которая позволяет создавать асинхронные, неблокирующие функции с использованием структуры, напоминающей обычные синхронные функции. Семантически и технически async/await связаны с концепцией корутин и зачастую реализуются схожими средствами. Основная цель использования такого подхода заключается в том, чтобы выполнять иной код программы во время ожидания завершения длительных асинхронных операций, обычно представляемых через промисы, фьючерсы или похожие структуры данных[1]. Подобная функциональность реализована в языках C#[1], C++, Python, F#, Hack, Julia, Dart, Kotlin, Rust[2], Nim[3], JavaScript (стандарт ECMAScript 2017) и Swift[4].

История

В 2007 году F# получил поддержку асинхронных рабочих процессов (asynchronous workflows) с точками ожидания (await points) в версии 2.0[5]. Эта функциональность была впервые представлена в виде отдельно устанавливаемого дополнения (Community Technology Preview) для Visual Studio 2008[6], а полная интеграция в среду разработки произошла с выходом Visual Studio 2010[7]. Эта реализация повлияла на появление механизма async/await в C#[8].

Компания Microsoft впервые реализовала поддержку async/await в экспериментальной версии C# Async CTP (2011). Официально эта функциональность стала частью языка с выпуском C# 5 (2012)[9][1].

Основной разработчик Haskell Саймон Марлоу (Simon Marlow) создал пакет async в 2012 году[10].

Поддержка async/await появилась в Python с выходом версии 3.5 (2015 год), где были добавлены два новых ключевых слова: async и await[11].

Официальная стабильная поддержка корутин, реализующих концепцию async/await, появилась в языке Kotlin с выходом версии 1.3 в октябре 2018 года[12].

В TypeScript аналогичная поддержка реализована с версии 1.7 (2015)[13]. Ключевым развитием стал выход TypeScript 2.1 (2016), в котором появилась возможность компиляции `async/await` для более старых версий JavaScript (ES3 и ES5), что сделало эту конструкцию доступной для использования в большинстве браузеров при наличии полифилла для `Promise`[14][15].

В JavaScript конструкция async/await появилась в стандарте ECMAScript 2017 (2017 год).

В Perl поддержка синтаксиса `async/await` реализуется через модули из репозитория CPAN. Ключевым является модуль `Future::AsyncAwait`, активная разработка которого велась в 2019 году Полом Эвансом[16]. Он предоставляет синтаксический сахар в виде ключевых слов `async sub` и `await` для работы с объектами `Future`, которые представляют отложенные вычисления, и используется в связке с фреймворками для асинхронного ввода-вывода, такими как `IO::Async`[17][18].

В Rust поддержка async/await появилась в версии 1.39.0 (2019 год) с использованием ключевого слова async и постфиксного оператора .await, введённых в редакции языка 2018 года[19].

В C++ официальная поддержка async/await реализована в стандарте C++20, где появились новые ключевые слова co_return, co_await и co_yield (2020 год).

Язык программирования Swift реализовал поддержку async/await с версии 5.5 (2021), добавив ключевые слова async и await. Эта версия также включает реализацию акторной модели с помощью ключевого слова actor, где для организации доступа к каждому актору используется async/await[20].

В 2025 году язык программирования Zig представил новую модель асинхронного ввода-вывода. Вместо синтаксиса `async/await` в традиционном виде, язык предлагает разделение вызова функции и возврата из неё, что позволяет выполнять несколько операций одновременно[21].

В феврале 2026 года с выходом предварительной версии стандарта WASI 0.3 в WebAssembly появилась нативная поддержка асинхронных операций, включая синтаксис, подобный `async/await`[22].

Новейшие разработки (2024—2026)

В 2024—2026 годах развитие асинхронного программирования было сосредоточено на улучшении эргономики, производительности и интеграции с существующими возможностями языков.

2024 год

  • JavaScript (ECMAScript 2024): Получил широкое распространение `Top-level await` (стандартизирован в ES2022), упрощающий инициализацию модулей[23]. Был добавлен новый статический метод `Array.fromAsync()` для создания массивов из асинхронных итерируемых объектов[24].
  • Rust (Edition 2024): Ключевым достижением стала стабилизация асинхронных функций в трейтах (`async fn in traits`)[24], что решило одну из главных проблем асинхронной экосистемы языка. В версии 1.85.0 (февраль 2025 года) была также добавлена поддержка асинхронных замыканий (`async closures`)[25].
  • C# (.NET 9): Был представлен метод `Task.WhenEach`, возвращающий `IAsyncEnumerable<Task<T>>` для обработки задач по мере их завершения. В C# 13 было снято ограничение на использование `ref`-переменных и `unsafe`-кода внутри `async`-методов (но не через границу `await`)[26]. Эксперименты с «зелёными потоками» были приостановлены в пользу улучшения существующей модели `async/await`[27].
  • Python (Python 3.13): Главным нововведением стала экспериментальная сборка CPython без глобальной блокировки интерпретатора (GIL), что открыло возможность для истинного многопоточного параллелизма в задачах, интенсивно использующих процессор.
  • Swift (Swift 6.0): Введена строгая проверка параллелизма по умолчанию и механизмы полной изоляции данных, направленные на предотвращение гонок данных на этапе компиляции[28].

2025 год

  • JavaScript (ECMAScript 2025): Добавлен новый статический метод `Promise.try()` для безопасной обёртки синхронных или асинхронных операций в `Promise`[29]. Также были улучшены производительность и обработка ошибок в циклах `for await...of`[30].
  • Zig: Представлена новая модель асинхронного ввода-вывода, которая вместо традиционного синтаксиса `async/await` использует разделение вызова функции и возврата из неё, позволяя выполнять несколько операций одновременно.
  • Swift: Продолжилось осмысление совместного использования `async/await` и фреймворка `Combine`. `async/await` рекомендуется для последовательных задач (например, сетевые запросы), а `Combine` — для работы с потоками данных в реальном времени (события UI, данные с сенсоров).
  • Node.js: Современные паттерны стали включать использование `async/await` в сочетании с новыми API, такими как `AsyncLocalStorage` для отслеживания состояния в асинхронных операциях[31].
  • Rust: В версии 1.85 (выпущена 20 февраля 2025 года) были стабилизированы асинхронные замыкания (async closures), что решило проблемы с заимствованием переменных из окружения и позволило использовать новые высокоуровневые типажи (AsyncFn, AsyncFnMut, AsyncFnOnce)[25].

2026 год

  • C++ (C++26): Принята модель Senders/Receivers (библиотека std::execution) для асинхронного и параллельного программирования[32].
  • WebAssembly: Выпущена предварительная версия стандарта WASI 0.3 с нативной поддержкой асинхронности[22].
  • Python (Python 3.14): Сборка без глобальной блокировки интерпретатора (free-threading) получила статус официально поддерживаемой[33].
  • Zig (Zig 0.16.0): Реализована новая модель ввода-вывода на основе интерфейса std.Io и возвращена поддержка async/await[34].

Пример (C#)

Ниже представлен пример функции на C#, использующей async/await для асинхронной загрузки ресурса по URI и возвращающей его размер:

public async Task<int> FindSizeOfPageAsync(Uri uri) 
{
    HttpClient client = new();
    byte[] data = await client.GetByteArrayAsync(uri);
    return data.Length;
}
  • Ключевое слово async показывает компилятору C#, что метод является асинхронным — то есть, внутри могут быть произвольные выражения await, а результат работы метода возвращается как промис (класс Task<T>)[1].
  • Тип возвращаемого значения Task<T> — в C# аналог промиса с результатом типа int.
  • Первое выражение при вызове метода — new HttpClient().GetByteArrayAsync(uri) которое также асинхронно: возвращает Task<byte[]>, и сразу запускает загрузку, возвращая неготовый результат.
  • С помощью ключевого слова await выполнение функции будет приостановлено до разрешения Task, после чего дальнейший код продолжится с получением значения data.
  • После завершения асинхронной операции функция возвращает data.Length, компилятор «оборачивает» возвращаемое значение в Task, вызывая колбэк у того, кто ожидал результат[1].,

Функция с async/await может содержать любое количество выражений await, каждое из которых будет обрабатываться аналогично. Функция может хранить промис вручную и выполнять дополнительную обработку до ожидания результата, а также агрегировать несколько промисов с помощью, например, Task.WhenAll(). В большинстве реализаций промисов также доступны дополнительные возможности: отслеживание прогресса, многочисленные колбэки и т.д.

В языке C# (и во многих других со схожей конструкцией) паттерн async/await реализован не на уровне рантайма, а компилятором посредством трансформации в лямбды или продолжения. Например, рассмотрим вариант, на который может быть преобразован рассмотренный выше код:

public Task<int> FindSizeOfPageAsync(Uri uri) 
{
    HttpClient client = new();
    Task<byte[]> dataTask = client.GetByteArrayAsync(uri);
    Task<int> afterDataTask = dataTask.ContinueWith((originalTask) => {
        return originalTask.Result.Length;
    });
    return afterDataTask;
}

Если методу интерфейса требуется возвращать промис, но внутри не нужны await, модификатор async не обязателен — промис возвращается напрямую (например Task.FromResult())[35].

Важная особенность: хотя код выглядит как блокирующий, в реальности выполнение не блокируется и может быть прервано внешними событиями, например, изменение разделяемого состояния между вызовами await:

string name = state.name;
HttpClient client = new();
byte[] data = await client.GetByteArrayAsync(uri);

// Возможна ошибка: state.a мог измениться внешним событием
Debug.Assert(name == state.name);

return data.Length;

Реализации

В C

Язык C напрямую конструкций `await`/`async` не имеет. Вместо этого асинхронное программирование и функциональность корутин (сопрограмм) реализуются с помощью сторонних библиотек. По состоянию на 2024—2025 годы их можно разделить на несколько категорий.

К современным и активно развивающимся библиотекам, предоставляющим каждой корутине собственный стек (stackful coroutines), относятся libaco и libcoro. libaco позиционируется как высокопроизводительное решение с поддержкой разделяемых стеков для экономии памяти, а libcoro — как простая и портируемая библиотека.

Для систем с жёсткими ограничениями по памяти, например, для встраиваемых систем, используется легковесный подход без выделения отдельных стеков (stackless). Представителем этого подхода является библиотека Protothreads, реализованная на макросах. Её недостатком является то, что локальные переменные не сохраняются между приостановками, и состояние приходится хранить в статических или глобальных переменных.

Некоторые популярные в прошлом библиотеки, такие как libdill и libmill, считаются устаревшими и не рекомендуются для новых проектов.

Примером библиотеки, имитирующей ключевые слова `await`/`async` с помощью макросов, является s_task[36]:

#include <stdio.h>
#include "s_task.h"

constexpr int STACK_SIZE = 64 * 1024 / sizeof(int);

// Определяем память для стека задач
int g_stack_main[STACK_SIZE];
int g_stack0[STACK_SIZE];
int g_stack1[STACK_SIZE];

void sub_task(__async__, void* arg) {
    int n = (int)(size_t)arg;
    for (int i = 0; i < 5; ++i) {
        printf("task %d, delay seconds = %d, i = %d\n", n, n, i);
        s_task_msleep(__await__, n * 1000);
        // s_task_yield(__await__);
    }
}

void main_task(__async__, void* arg) {
    // Запуск двух задач
    s_task_create(g_stack0, sizeof(g_stack0), sub_task, (void*)1);
    s_task_create(g_stack1, sizeof(g_stack1), sub_task, (void*)2);

    for (int i = 0; i < 4; ++i) {
        printf("task_main arg = %p, i = %d\n", arg, i);
        s_task_yield(__await__);
    }

    // Ждём завершения обеих задач
    s_task_join(__await__, g_stack0);
    s_task_join(__await__, g_stack1);
}

int main(int argc, char* argv[]) {
    s_task_init_system();

    // Запуск главной задачи
    s_task_create(g_stack_main, sizeof(g_stack_main), main_task, (void*)(size_t)argc);
    s_task_join(__await__, g_stack_main);
    printf("all task is over\n");
    return 0;
}

В C++

В C++ оператор await (называемый co_await для ясности контекста корутин) официально включён в стандарт C++20[37]. Его поддерживают компиляторы GCC и MSVC; в Clang — частично.

Базовые классы std::promise и std::future сами по себе не выполняют требований для await; необходимо реализовать методы await_ready, await_suspend и await_resume в возвращаемом типе. Детали можно изучить на cppreference[38].

Пример класса AwaitableTask<T> с поддержкой co_await:

import std;
import org.wikipedia.util.AwaitableTask;

using org::wikipedia::util::AwaitableTask;

AwaitableTask<int> add(int a, int b) {
    int c = a + b;
    co_return c;
}

AwaitableTask<int> test() {
    int ret = co_await add(1, 2);
    std::println("Return {}", ret);
    co_return ret;
}

int main() {
    AwaitableTask<int> task = test();

    return 0;
}

В стандарте C++23 не появилось кардинально новых механизмов асинхронности, однако были добавлены улучшения в стандартную библиотеку. Ключевым дополнением стал std::generator — первый стандартный тип корутины, который представляет собой простой способ создания генератора — функции, способной приостанавливать своё выполнение, возвращая последовательность значений[39]. Также был добавлен тип std::expected, предоставляющий удобный способ для возврата из функции либо успешного результата, либо ошибки, что является частым сценарием в асинхронных операциях[40].

Наиболее значительные изменения в области асинхронности произошли в стандарте C++26, в который была официально принята модель Senders/Receivers (предложение P2300, добавляющее библиотеку std::execution), предоставившая единый фреймворк для асинхронного и параллельного программирования[41][32]. Изначально её принятие рассматривалось для C++23, но было отложено[42]. Эта модель предлагает высокоуровневую композитную абстракцию для управления вычислительными ресурсами. Основные концепции:

  • Sender (отправитель) — ленивая асинхронная операция, которую можно объединять в цепочки, формируя граф вычислений[43].
  • Receiver (получатель) — объект, который потребляет результат, ошибку или сигнал отмены от Sender'а.
  • Scheduler (планировщик) — абстракция, определяющая, где и как будет выполняться работа (например, в пуле потоков, главном потоке или на GPU)[41][32].

Модель std::execution тесно интегрирована с корутинами: Sender-ы являются ожидаемыми, и к ним можно напрямую применять оператор co_await, что обеспечивает их бесшовное использование в асинхронных функциях[41][32].

В C#

В 2012 году в языке C# появился паттерн async/await (версия 5.0), — этот подход Microsoft называет task-based asynchronous pattern (TAP)[44]. Обычно асинхронные методы возвращают void, Task, Task<T>, ValueTask или ValueTask<T>[45].

В редких случаях могут использоваться пользовательские типы возврата (через кастомные async method builders). Методы, возвращающие void, предназначены для обработчиков событий; в других случаях лучше использовать Task для удобства обработки исключений[46].

Эволюция возможностей

  • C# 6.0 (2015): Появилась возможность использовать оператор `await` в блоках `catch` и `finally`[47], что значительно упростило асинхронную обработку ошибок и очистку ресурсов.
  • C# 7.0 / 7.1 (2017): Были введены обобщённые асинхронные возвращаемые типы. Ключевым примером стал тип-значение `ValueTask<T>`, позволяющий избежать выделения памяти в куче для методов, которые часто завершаются синхронно (например, при чтении из кэша)[48]. В C# 7.1 была добавлена поддержка асинхронного метода `Main`, что упростило запуск консольных приложений с асинхронными операциями на верхнем уровне[49].
  • C# 8.0 (2019): Появились асинхронные потоки. Эта возможность включает интерфейс `IAsyncEnumerable<T>` для представления асинхронных последовательностей и конструкцию `await foreach` для их перебора[50][51]. Также был добавлен интерфейс `IAsyncDisposable` и оператор `await using` для асинхронного освобождения ресурсов[50].
  • C# 10 (2021): Появилась возможность применять атрибут `[AsyncMethodBuilder]` непосредственно к методу, а не только к возвращаемому типу. Это предоставило разработчикам библиотек расширенные средства для оптимизации производительности, например, через создание пулов объектов-строителей асинхронных методов[52][53].
  • C# 13 (2024): Было снято ограничение на использование типов `ref struct` (таких как `Span<T>`) и `unsafe`-кода внутри `async`-методов. Это позволяет писать более производительный код с меньшим количеством выделений памяти, однако такие переменные не могут использоваться через границу оператора `await`[54][55].
  • .NET 10 / 11: Представлена экспериментальная функция Runtime-Async, переносящая логику управления асинхронностью из компилятора непосредственно в среду выполнения. Вместо генерации сложных конечных автоматов компилятором, среда выполнения сама управляет приостановкой и возобновлением методов. Это нововведение направлено на повышение производительности за счёт снижения количества аллокаций памяти и улучшение возможностей JIT-оптимизации, а также позволяет формировать более чистые и линейные трассировки стека вызовов, что значительно упрощает отладку. В .NET 10 функция доступна в режиме предварительного просмотра, а её полноценное включение планируется в .NET 11[56][57][58].

В F#

В F# с версии 2.0 (2007) поддержаны асинхронные рабочие процессы (asynchronous workflows), реализованные через вычислительные выражения (computation expressions)[59]. Ключевой особенностью этой модели, оказавшей влияние на C#, является концепция «холодных» задач. В отличие от «горячих» задач в C#, которые запускаются сразу, блок `async { ... }` в F# создаёт объект `Async<'T>`, который является лишь описанием вычисления и не запускается немедленно[60]. Для фактического выполнения необходимо явно вызвать одну из стартовых функций, например `Async.RunSynchronously` или `Async.StartAsTask`[61]. Внутри асинхронного блока для ожидания результата другой операции используются ключевые слова `let!` (для связывания результата с переменной) и `do!` (для выполнения операции, не возвращающей значимого результата)[62].

Эволюция и новые возможности

  • F# 5 (2020): Была введена поддержка аппликативных вычислительных выражений с помощью ключевого слова `and!`. В отличие от последовательного `let!`, `and!` позволяет выполнять несколько независимых асинхронных операций параллельно, если это поддерживается строителем вычислительного выражения[63].
  • F# 6 (2021): Появились более производительные вычислительные выражения `task { ... }`, которые напрямую работают с задачами .NET (`System.Threading.Tasks.Task<'T>`)[64]. Этот подход обеспечивает лучшую совместимость с C# и другими .NET-библиотеками, а также имеет меньшие накладные расходы и улучшенную поддержку отладки по сравнению с традиционными `async { ... }`[64]. Выражения `task { ... }` основаны на низкоуровневой функции «возобновляемый код» (resumable code) и рекомендуются для нового кода, взаимодействующего с экосистемой .NET[65].

Пример функции, скачивающей несколько страниц асинхронно с использованием традиционного `async`-выражения:

let asyncSumPageSizes (uris: #seq<Uri>) : Async<int> = async {
    use httpClient = new HttpClient()
    let! pages = 
        uris
        |> Seq.map(httpClient.GetStringAsync >> Async.AwaitTask)
        |> Async.Parallel
    return pages |> Seq.fold (fun accumulator current -> current.Length + accumulator) 0
}

В Haskell

В языке Haskell отсутствует встроенная синтаксическая конструкция async/await, подобная той, что используется в C# или JavaScript. Вместо этого асинхронность реализуется на библиотечном уровне, где ключевую роль играет пакет async, созданный одним из ведущих разработчиков Haskell Саймоном Марлоу в 2012 году[66][67]. Эта библиотека предоставила более высокоуровневый и безопасный интерфейс по сравнению с базовым примитивом forkIO, использование которого было сопряжено с трудностями в обработке исключений и получении результата выполнения фоновой задачи[68].

Подход, предложенный библиотекой, концептуально схож с паттерном async/await и основан на нескольких ключевых функциях:

  • async :: IO a -> IO (Async a) — запускает IO-действие в отдельном легковесном потоке и немедленно возвращает «обещание» результата типа Async a[69]. Это аналог запуска асинхронной задачи.
  • wait :: Async a -> IO a — ожидает завершения асинхронной операции и возвращает её результат. Если в ходе вычисления произошло исключение, wait повторно выбрасывает его в вызывающем потоке, что делает обработку ошибок предсказуемой[69]. Это является прямым аналогом оператора await.

Сочетание этих функций внутри монадического блока do позволяет писать асинхронный код, который выглядит как последовательный.

Библиотека также реализует принципы структурного параллелизма. Функция withAsync гарантирует, что порождённый асинхронный поток будет автоматически отменён при выходе из блока, даже в случае исключения, что предотвращает утечки потоков[70]. Для композиции задач предусмотрены комбинаторы, такие как race (возвращает результат первой завершившейся задачи, отменяя остальные) и concurrently (выполняет две задачи параллельно и возвращает оба результата)[71].

Данный подход был подробно описан и популяризирован в книге Саймона Марлоу «Parallel and Concurrent Programming in Haskell» (2013)[72].

Пример параллельного выполнения двух операций:

import Control.Concurrent.Async (async, wait)
import Control.Concurrent (threadDelay)
import Text.Printf (printf)

-- Асинхронная операция, имитирующая долгую работу
longOperation :: String -> Int -> IO String
longOperation name delaySec = do
    threadDelay (delaySec * 1000000) -- задержка в микросекундах
    let result = printf "Операция '%s' завершена" name
    return result

main :: IO ()
main = do
    putStrLn "Запуск двух асинхронных операций..."
    -- Запускаем обе операции параллельно, не дожидаясь их завершения
    task1 <- async (longOperation "A" 2)
    task2 <- async (longOperation "B" 1)

    putStrLn "Операции запущены. Основной поток может выполнять другую работу."

    -- Ожидаем результат сначала от второй, затем от первой операции
    result2 <- wait task2
    putStrLn result2

    result1 <- wait task1
    putStrLn result1

В Java

В языке Java отсутствует встроенный синтаксис async/await. Разработчики языка сознательно выбрали путь развития, альтернативный добавлению синтаксического сахара, сосредоточившись на фундаментальных улучшениях виртуальной машины Java (JVM)[73].

Долгое время основным инструментом для организации асинхронных операций служил класс `CompletableFuture`, представленный в Java 8. Он позволяет создавать цепочки асинхронных вычислений и считается ближайшим функциональным аналогом `async/await`[74][75].

Ключевым нововведением, ставшим общедоступным с выходом Java 21, стали виртуальные потоки (Virtual Threads), разработанные в рамках проекта Project Loom[76]. Этот подход позволяет писать код в привычном последовательном (синхронном) стиле, который при этом выполняется асинхронно и не блокирует потоки операционной системы. Виртуальные потоки являются легковесными, управляются самой JVM и предназначены в первую очередь для задач, связанных с вводом-выводом (I/O-bound), таких как сетевые запросы[77].

В дополнение к виртуальным потокам развивается концепция структурированной конкурентности (Structured Concurrency), которая в 2024 году находилась в статусе предварительной версии (Preview Feature). Она предлагает API `StructuredTaskScope` для управления группой связанных задач как единым целым, что упрощает обработку ошибок и отмену операций[73].

Несмотря на выбранный платформой путь, существуют сторонние библиотеки, которые реализуют синтаксис, подобный `async/await`, с помощью инструментов обработки байт-кода, однако они не являются частью стандартной платформы Java[78].

Технология Scoped Values была финализирована в Java 25[79], а Structured Concurrency остаётся в статусе предварительной версии (preview) вплоть до Java 26[80].

В JavaScript

В JavaScript оператор await работает только внутри функции, отмеченной async, либо на верхнем уровне модуля. Если параметр — промис, выполнение возобновляется при его завершении (или возбуждается ошибка при отклонении), если нет — возвращается само значение[81]. Многие библиотеки возвращают совместимые промисы (Promises/A+). Однако, промисы из библиотеки jQuery до версии 3.0 не соответствовали стандарту[82].

Пример:

async function createNewDoc() {
  let response = await db.post({});
  return db.get(response.id);
}

async function main() {
  try {
    let doc = await createNewDoc();
    console.log(doc);
  } catch (err) {
    console.log(err);
  }
}
main();

Эволюция возможностей и новые API

С момента введения `async/await` в стандарте ECMAScript 2017, функциональность асинхронного программирования постоянно расширялась.

ECMAScript 2018 представил асинхронные итераторы и цикл for-await-of[83]. Это позволило работать с асинхронно поступающими данными (например, из потоков) в виде последовательных итераций. Также был добавлен метод Promise.prototype.finally(), который выполняет код после завершения промиса, независимо от его исхода (успех или ошибка).

ECMAScript 2020 добавил метод Promise.allSettled(), который ожидает завершения всех промисов в массиве, возвращая массив объектов с их статусами и результатами, даже если некоторые из них были отклонены[84]. В отличие от `Promise.all()`, он не прерывается при первой ошибке. Также был стандартизирован динамический импорт `import()`, который возвращает промис и позволяет асинхронно загружать модули по требованию[85].

ECMAScript 2022 стандартизировал top-level await (верхнеуровневый `await`), который позволяет использовать `await` на верхнем уровне ES-модулей без необходимости оборачивать код в `async`-функцию[86]. Эта возможность, поддержка которой в основных браузерах и Node.js появилась в 2021 году, значительно упрощает асинхронную инициализацию модулей[86].

ECMAScript 2024 ввёл новый статический метод Array.fromAsync() для создания массивов из асинхронных итерируемых объектов[24].

ECMAScript 2025 включил статический метод Promise.try() для унифицированной обработки ошибок[29]. Также стандарт закрепил метод Array.fromAsync(), позволяющий лаконично собирать элементы асинхронного потока в массив без ручного использования цикла for await...of[30].

В Node.js

В Node.js с версии 8 присутствуют удобные средства обёртывания callback-функций в промисы с помощью `util.promisify`[87]. Ключевые улучшения для асинхронного программирования были внесены в Node.js 12 (2019 год). Благодаря оптимизациям в движке V8, выполнение `async/await` стало значительно быстрее, в некоторых случаях превосходя по скорости код, написанный вручную с использованием промисов[88]. Кроме того, появились асинхронные стектрейсы, которые значительно упростили отладку: если раньше трассировка стека обрывалась на операторе `await`, то теперь она включает полную цепочку асинхронных вызовов, показывая весь контекст возникновения ошибки[89]. Начиная с версии Node.js 16, механизм «zero-cost async stack traces» (бесплатных асинхронных стектрейсов) стал стабильным и включён по умолчанию, что устранило необходимость явного указания флага --async-stack-traces[88].

В Kotlin

Официальная стабильная поддержка корутин, реализующих концепцию async/await, появилась в языке Kotlin с выходом версии 1.3 в октябре 2018 года[12]. До этого момента они существовали в экспериментальном статусе. Релиз Kotlin 1.3 ознаменовал стабилизацию как языковой поддержки, так и сопутствующей библиотеки kotlinx.coroutines, которая вышла в версии 1.0[90]. Это сделало корутины готовыми для использования в производственной среде, предоставив разработчикам инструмент для написания асинхронного и неблокирующего кода.

В Perl 5

В языке Perl 5 синтаксис async/await не является встроенной возможностью ядра, а реализуется через модули из репозитория CPAN[91]. Ключевым является модуль Future::AsyncAwait, разработанный Полом Эвансом при поддержке гранта от The Perl Foundation в 2018 году[92].

Модуль предоставляет синтаксический сахар в виде ключевых слов async sub и await для работы с объектами Future, которые представляют отложенные вычисления[93]. Это позволяет писать асинхронный код в более простом и читаемом последовательном стиле, избегая сложных цепочек вызовов `->then()` (так называемого «ада колбэков»)[94]. Активная разработка модуля велась в 2019 году, в течение которого было выпущено множество версий с исправлениями и улучшениями[95]. К 2021—2025 годам модуль стал стабильным и активно поддерживаемым решением[96].

Future::AsyncAwait является синтаксической надстройкой и используется в связке с фреймворками для асинхронного ввода-вывода, такими как IO::Async[97]. Популярный веб-фреймворк Mojolicious также поддерживает `async/await` на его основе[98]. Несмотря на популярность этого подхода, синтаксис `async/await` не был включён в ядро языка, в том числе в стабильную версию Perl 5.42 (сентябрь 2025 года)[99].

В Python

В Python поддержка async/await реализована начиная с версии 3.5 (2015)[100], согласно PEP 492 (автор — Юрий Селиванов)[101].

Эволюция возможностей

С момента введения синтаксис и библиотека asyncio получили значительное развитие:

  • Python 3.6 (2016): Были добавлены асинхронные генераторы (async def с yield, PEP 525) и асинхронные comprehensions (async for в списковых включениях, PEP 530)[102]. Модуль asyncio был признан стабильным, а не временным API[103].
  • Python 3.11 (2022): Представлены группы задач (asyncio.TaskGroup) для реализации концепции структурированной конкурентности[104]. Этот механизм, использующий синтаксис асинхронного менеджера контекста (async with), гарантирует, что все порождённые задачи будут завершены до выхода из блока, и автоматически отменяет оставшиеся задачи при возникновении ошибки в одной из них[105]. Для обработки ошибок из нескольких задач одновременно были введены группы исключений (ExceptionGroup) и новый синтаксис except*[106].
  • Python 3.12 (2023): Основной упор был сделан на повышение производительности (в некоторых тестах до 75 %)[107] и надёжности. В модуль был добавлен механизм «нетерпеливого» выполнения задач (eager task execution) через asyncio.eager_task_factory(), при котором корутина начинает исполняться синхронно в момент создания задачи и передаётся в цикл событий только при блокировке, что позволяет избежать накладных расходов на планирование[108][109].
  • Python 3.13 (2024): Главным нововведением стала экспериментальная сборка CPython без глобальной блокировки интерпретатора (GIL), предложенная в PEP 703. Это открыло возможность для истинного многопоточного параллелизма в задачах, интенсивно использующих процессор, и дало разработчикам новый инструмент для конкурентного выполнения кода наряду с asyncio[110]. В версии Python 3.14 сборка без GIL (free-threading) перешла из экспериментального статуса в официально поддерживаемый[33].
  • Python 3.14 (2025): Были добавлены встроенные инструменты для интроспекции и отладки. Команды python -m asyncio ps и python -m asyncio pstree позволяют просматривать активные асинхронные задачи в работающем процессе[111]. Для интерактивной отладки появилась функция pdb.set_trace_async(), позволяющая использовать await внутри сессии отладчика pdb[112]. Кроме того, в сборках без GIL цикл событий asyncio стал потокобезопасным[112].
import asyncio

async def main() -> None:
    print("hello")
    await asyncio.sleep(1)
    print("world")

if __name__ == "__main__":
    asyncio.run(main())

В Rust

7 ноября 2019 года `async/await` стали доступны в стабильной версии Rust 1.39.0[113]. Асинхронные функции преобразуются компилятором в функции, возвращающие объект, реализующий трейт `Future` (и реализуются как конечный автомат)[114].

Ключевым этапом для экосистемы стал выпуск в декабре 2020 года асинхронной среды выполнения (runtime) Tokio версии 1.0, что ознаменовало готовность `async/await` для широкого промышленного использования[115]. Tokio предоставляет инструменты для написания сетевых приложений и сервисов, а макрос `#[tokio::main]` упрощает запуск асинхронных программ. Долгое время альтернативой выступала среда `async-std`, однако в марте 2025 года этот проект был официально прекращён, и экосистема окончательно консолидировалась вокруг Tokio[116][117].

Эволюция возможностей

  • Rust 1.75 (декабрь 2023): Была стабилизирована одна из самых ожидаемых возможностей — поддержка асинхронных функций в трейтах (async fn in traits, AFIT). Это решило одну из главных проблем асинхронного Rust, позволив создавать более гибкие и универсальные абстракции для асинхронного кода[118][119].
  • Rust 1.85 (февраль 2025): В версии, стабилизировавшей редакцию языка Rust 2024, была добавлена поддержка асинхронных замыканий (`async closures`) и связанных с ними трейтов `AsyncFn`, `AsyncFnMut` и `AsyncFnOnce`. Это позволяет создавать замыкания вида `async || {}`, которые возвращают `Future` и могут заимствовать данные из окружения, что упрощает использование асинхронного кода в функциональных паттернах[25][120].
  • По состоянию на 2026 год асинхронные итераторы (`AsyncIterator`) и асинхронные деструкторы (`Async Drop`) всё ещё не стабилизированы[121][122].
// В Cargo.toml: tokio = { version = "1", features = ["full"] }

use std::time::Duration;

async fn first_task() {
    println!("Задача 1 началась");
    tokio::time::sleep(Duration::from_secs(2)).await;
    println!("Задача 1 завершилась");
}

async fn second_task() {
    println!("Задача 2 началась");
    tokio::time::sleep(Duration::from_secs(1)).await;
    println!("Задача 2 завершилась");
}

#[tokio::main]
async fn main() {
    // Запускаем обе задачи параллельно
    tokio::join!(first_task(), second_task());
}

В Swift

C версии 5.5 (2021) в Swift поддерживается async/await согласно спецификации SE-0296[123].

Эволюция возможностей

  • Swift 5.7 (2022): Был выпущен open-source пакет Swift Async Algorithms, расширяющий возможности работы с асинхронными последовательностями (AsyncSequence) с помощью таких операторов, как `zip`, `merge`, `throttle` и `debounce`[124]. Также были представлены новые API для работы со временем (`Clock`, `Instant`, `Duration`), что позволило улучшить управление асинхронными задачами, например, через обновлённую функцию `Task.sleep`[124].
  • Swift 5.9 (2023): Были представлены группы отбрасываемых задач (Discarding Task Groups), которые решают проблему накопления результатов и потенциальной утечки памяти в долгоживущих серверных приложениях[125]. Также появилась возможность создавать пользовательские исполнители акторов (custom actor executors) для низкоуровневого управления контекстом выполнения акторов[125].
  • Swift 6 (2024): Ключевым изменением стало включение по умолчанию режима строгой проверки параллелизма и механизмов изоляции данных. Предупреждения о потенциальных гонках данных (data races) стали ошибками компиляции, что заставляет разработчиков обеспечивать безопасность доступа к данным на этапе написания кода[28][126].
  • Swift 6.2 (2025): В рамках концепции «доступной многопоточности» (Approachable Concurrency) было изменено поведение по умолчанию: теперь асинхронная функция продолжает выполняться в том же контексте (акторе), из которого была вызвана, что делает код более предсказуемым, особенно при работе с `@MainActor`[127]. Для явного указания, что функция должна выполняться в фоновом потоке, был добавлен атрибут `@concurrent`[128].
func getNumber() async throws -> Int {
    try await Task.sleep(nanoseconds: 1_000_000_000)
    return 42
}

Task {
    let first = try await getNumber()
    let second = try await getNumber()
    print(first + second)
}

В TypeScript

В TypeScript поддержка `async/await` была реализована в версии 1.7 (2015). Ключевым развитием стал выход TypeScript 2.1 (декабрь 2016), в котором появилась возможность компиляции (`downleveling`) конструкций `async/await` для более старых версий JavaScript (ES3 и ES5). Это сделало данную возможность доступной для использования в большинстве браузеров при условии наличия полифилла для `Promise`[129]. Для этого компилятор преобразует асинхронную функцию в машину состояний с использованием генераторов и вспомогательной функции `__awaiter`[129].

Дальнейшее развитие было направлено на улучшение работы с типами и интеграцию с новыми возможностями ECMAScript. В TypeScript 4.5 (ноябрь 2021) были представлены[130]:

  • `Awaited<T>` — новый служебный тип, который рекурсивно «разворачивает» промисы для получения конечного типа значения. Он используется для улучшения вывода типов в таких методах, как `Promise.all`[131][130].
  • `Top-level await` — поддержка `await` на верхнем уровне ES-модулей без необходимости оборачивать код в `async`-функцию, что упрощает асинхронную инициализацию. Для этого требуется опция компилятора `--module es2022`[132][130].

В TypeScript 5.2 (август 2023) была добавлена поддержка явного управления асинхронными ресурсами с помощью конструкции `await using`[133]. Этот синтаксис автоматически вызывает и ожидает завершения метода, определённого в `Symbol.asyncDispose`, при выходе из блока, что обеспечивает надёжное асинхронное освобождение ресурсов[134].

class DatabaseConnection implements AsyncDisposable {
  async connect() { /* ... */ }
  async close() { /* ... */ }

  async [Symbol.asyncDispose]() {
    await this.close();
  }
}

async function queryDatabase() {
  await using db = new DatabaseConnection();
  await db.connect();
  // ... работа с базой данных
} // db.close() будет вызван и дождан здесь автоматически

В WebAssembly

В феврале 2026 года была выпущена предварительная версия стандарта WASI 0.3 (Preview 3), которая добавила в WebAssembly нативную поддержку асинхронных операций. Основным нововведением стала интеграция асинхронности непосредственно на уровень компонентной модели (Component Model) через канонический ABI (Application Binary Interface) с помощью новых типов future<T> и stream<T>[22].

Это позволило объявлять функции как async прямо в их интерфейсах (WIT), при этом среда выполнения прозрачно управляет их асинхронным исполнением. Благодаря этому разработчики получили возможность использовать привычные конструкции async/await из своих языков программирования (например, Rust, JavaScript, Python, C#), которые транслируются в единый механизм на уровне WebAssembly. Данное нововведение решило проблему предыдущей версии WASI 0.2, где асинхронные операции требовали сложной ручной обработки[22].

В Zig

В версии языка программирования Zig 0.16.0, выпущенной в 2026 году, была реализована новая модель асинхронности, основанная на интерфейсе std.Io. Это обновление ознаменовало возвращение ключевых слов async и await, которые присутствовали в ранних версиях языка, но были временно удалены в релизах 0.11.0—0.12.0 для фундаментальной переработки[34].[135]

Новая система ввода-вывода построена вокруг интерфейса std.Io, который передаётся в функции в качестве параметра аналогично интерфейсу Allocator для управления памятью. Такой подход решает проблему «цветных функций», позволяя одному и тому же коду работать как в синхронном, так и в асинхронном режиме в зависимости от переданной реализации[136]. Стандартная библиотека предоставляет несколько вариантов интерфейса, включая std.Io.Threaded на основе пула потоков и событийно-ориентированную std.Io.Evented, использующую системные API (например, io_uring в Linux и kqueue в macOS)[137].

В рамках этой модели ключевое слово async используется для отделения вызова функции от её завершения, а await — для ожидания результата. При этом в языке проводится чёткое разделение между асинхронностью (возможностью неупорядоченного выполнения) и параллелизмом (одновременным выполнением): для задач, требующих параллельного выполнения, предназначена отдельная функция concurrent[34].[137]

Преимущества и критика

Поддержка async/await особенно интересна для языков, не имеющих управляемого рантайма: реализации полностью ограничиваются трансформацией функций в конечный автомат на стадии компиляции[138].

Сторонники async/await утверждают, что синтаксис позволяет писать неблокирующий асинхронный код, очень похожий на традиционный синхронный, что повышает удобство и читаемость и делает код с await почти столь же простым для понимания, как блокирующий[139]. Это облегчает создание надёжного асинхронного ПО, требующего сложной обработки событий.

Критики async/await отмечают, что паттерн «распространяется» на окружающий код, порождая проблему разделения экосистемы библиотек на синхронные и асинхронные («окрашивание функций», function coloring)[140]. Альтернативой являются «бесцветные» (colorless) модели (например, гороутины Go или виртуальные потоки Java)[141]. Показательным примером поиска решения этой проблемы являются эксперименты команды .NET с «зелёными потоками», которые могли бы устранить необходимость в async/await. Однако в 2024 году было решено приостановить эту работу в пользу улучшения существующей модели из-за сложности внедрения второго подхода к параллелизму и проблем с производительностью. На смену этим экспериментам в .NET 10 и 11 пришла новая архитектура Runtime-Async, которая значительно улучшает производительность за счёт переноса управления асинхронностью на уровень среды выполнения, но при этом не решает фундаментальную проблему «окрашивания функций»[142][57][58].

Примечания

  1. 1 2 3 4 5 Skeet, Jon. C# in Depth. — Manning, 23 марта 2019. — ISBN 978-1617294532.
  2. Announcing Rust 1.39.0 (англ.). Дата обращения: 29 мая 2026. Архивировано 26 июня 2025 года.
  3. std/async (англ.). Дата обращения: 29 мая 2026. Архивировано 29 сентября 2025 года.
  4. Concurrency — The Swift Programming Language (Swift 5.5). docs.swift.org. Дата обращения: 29 мая 2026. Архивировано 11 октября 2025 года.
  5. Syme, Don. The F# Asynchronous Programming Model // Practical Aspects of Declarative Languages : [англ.] / Don Syme, Tomas Petricek, Dmitry Lomov. — Springer Link, 2011. — Vol. 6539. — P. 175–189. — ISBN 978-3-642-18377-5. — doi:10.1007/978-3-642-18378-2_15.
  6. Sanchez, Ed The First Visual F# CTP is Here. weblogs.asp.net (17 октября 2007). Дата обращения: 29 мая 2026. Архивировано 3 февраля 2023 года.
  7. Syme, Don; Petricek, Tomas; Lomov, Dmitry The Early History of F# (pdf). fsharp.org (2020). Дата обращения: 29 мая 2026. Архивировано 10 октября 2025 года.
  8. The Early History of F#, HOPL IV (англ.). ACM Digital Library. Дата обращения: 29 мая 2026. Архивировано 6 мая 2025 года.
  9. Hejlsberg, Anders Anders Hejlsberg: Introducing Async – Simplifying Asynchronous Programming (англ.). Channel 9 MSDN. Microsoft. Дата обращения: 29 мая 2026. Архивировано 31 октября 2010 года.
  10. async: Run IO operations asynchronously and wait for their results. Hackage. Дата обращения: 29 мая 2026. Архивировано 12 августа 2025 года.
  11. What's New In Python 3.5 — Python 3.9.1 documentation. docs.python.org. Дата обращения: 29 мая 2026. Архивировано 20 ноября 2025 года.
  12. 1 2 What's New in Kotlin 1.3. Kotlin Documentation (29 октября 2018). Дата обращения: 29 мая 2026.
  13. Gaurav, Seth Announcing TypeScript 1.7. TypeScript. Microsoft (30 ноября 2015). Дата обращения: 29 мая 2026. Архивировано 23 июня 2025 года.
  14. Krogh, Daniel Announcing TypeScript 2.1. TypeScript. Microsoft (7 декабря 2016). Дата обращения: 29 мая 2026. Архивировано 16 июля 2025 года.
  15. TypeScript 2.1 Released, Adds Downlevel Async/Await. InfoQ (8 декабря 2016). Дата обращения: 3 ноября 2025. Архивировано 14 февраля 2025 года.
  16. Grant Proposal: Future::AsyncAwait. The Perl Foundation (29 октября 2018). Дата обращения: 29 мая 2026. Архивировано 14 августа 2021 года.
  17. Future::AsyncAwait - deferred subroutines using async/await. metacpan.org. Дата обращения: 29 мая 2026. Архивировано 26 марта 2019 года.
  18. IO::Async - Asynchronous event-driven programming. metacpan.org. Дата обращения: 29 мая 2026. Архивировано 19 мая 2025 года.
  19. Matsakis, Niko Async-await on stable Rust! (англ.). blog.rust-lang.org. Rust Blog. Дата обращения: 29 мая 2026. Архивировано 9 сентября 2025 года.
  20. Concurrency — the Swift Programming Language (Swift 5.6). Дата обращения: 29 мая 2026. Архивировано 11 октября 2025 года.
  21. Эндрю Келли, создатель языка Zig, анонсировал будущее асинхронного I/O. Habr (10 октября 2025). Дата обращения: 29 мая 2026.
  22. 1 2 3 4 WASI 0.3 Native Async: WebAssembly Gets Concurrent I/O. Byte Iota (февраль 2026). Дата обращения: 29 мая 2026.
  23. Breaking Down Python 3.13’s Latest Features. Awesome Analytics. Дата обращения: 29 мая 2026. Архивировано 24 июня 2025 года.
  24. 1 2 3 Async Rust in 2024. smallcultfollowing.com (3 января 2024). Дата обращения: 29 мая 2026. Архивировано 24 мая 2025 года.
  25. 1 2 3 Announcing Rust 1.85.0. Rust Blog (20 февраля 2025). Дата обращения: 29 мая 2026. Архивировано 21 ноября 2025 года.
  26. Releases · Kotlin/kotlinx.coroutines. GitHub. Дата обращения: 29 мая 2026. Архивировано 9 октября 2025 года.
  27. What is the future goal of async Rust? Rust Programming Language Forum. Дата обращения: 29 мая 2026. Архивировано 19 сентября 2025 года.
  28. 1 2 Swift 6: Полная проверка параллельности по умолчанию. Habr. Дата обращения: 29 мая 2026. Ошибка в сносках?: Неверный тег <ref>: название «HabrSwift6» определено несколько раз для различного содержимого
  29. 1 2 Что нового в ECMAScript 2025 — с примерами кода и комментариями экспертов. Типичный программист. Дата обращения: 3 ноября 2025. Архивировано 20 сентября 2025 года.
  30. 1 2 What's New in JavaScript ES2025. NamasteDev. Дата обращения: 29 мая 2026.
  31. Современные паттерны в Node.js в 2025 году. Node.js Разработка. Дата обращения: 3 ноября 2025. Архивировано 9 августа 2025 года.
  32. 1 2 3 4 stdexec: C++26 std::execution reference implementation. GitHub. NVIDIA. Дата обращения: 29 мая 2026.
  33. 1 2 Free-threaded mode improvements in Python 3.14. gdevops.frama.io. Дата обращения: 29 мая 2026.
  34. 1 2 3 Async/await is finally back in Zig! DEV Community. Дата обращения: 29 мая 2026.
  35. Albahari, Joseph. C# 10 in a Nutshell. — O'Reilly, 2022. — ISBN 978-1-098-12195-2.
  36. s_task - awaitable coroutine library for C. GitHub. Дата обращения: 29 мая 2026. Архивировано 8 октября 2024 года.
  37. ISO C++ Committee announces that C++20 design is now feature complete (25 февраля 2019). Дата обращения: 29 мая 2026. Архивировано 27 февраля 2019 года.
  38. Coroutines (C++20). Дата обращения: 29 мая 2026. Архивировано 3 декабря 2019 года.
  39. std::generator - cppreference.com. cppreference.com. Дата обращения: 29 мая 2026. Архивировано 1 января 2023 года.
  40. cpp-async. GitHub. Дата обращения: 29 мая 2026. Архивировано 18 марта 2025 года.
  41. 1 2 3 std::execution: будущее асинхронности в C++26. Habr (15 мая 2025). Дата обращения: 29 мая 2026.
  42. P2500R2: Sender/Receiver is not ready for C++23. open-std.org (13 февраля 2023). Дата обращения: 29 мая 2026. Архивировано 4 августа 2025 года.
  43. P0443R14: A Unified Executors Proposal for C++. open-std.org (9 октября 2020). Дата обращения: 29 мая 2026. Архивировано 29 сентября 2025 года.
  44. Task-based asynchronous pattern. Microsoft. Дата обращения: 29 мая 2026. Архивировано 23 сентября 2017 года.
  45. Price, Mark J. C# 8.0 and .NET Core 3.0 – Modern Cross-Platform Development. — Packt, 2022. — ISBN 978-1-098-12195-2.
  46. Stephen Cleary. Async/Await - Best Practices in Asynchronous Programming
  47. Using await in catch and finally block, a new feature of C#. C-Sharp Corner. Дата обращения: 29 мая 2026. Архивировано 15 января 2025 года.
  48. What’s New in C# 7.0. Microsoft. Дата обращения: 29 мая 2026. Архивировано 29 сентября 2025 года.
  49. Оператор await — асинхронно ожидает завершения задачи. Microsoft Learn. Дата обращения: 29 мая 2026. Архивировано 7 сентября 2025 года.
  50. 1 2 Асинхронные потоки. Metanit. Дата обращения: 29 мая 2026. Архивировано 20 марта 2023 года.
  51. Асинхронные стримы в C# 8. Habr (20 августа 2019). Дата обращения: 29 мая 2026.
  52. Allow AsyncMethodBuilder attribute on methods. Microsoft Learn. Дата обращения: 29 мая 2026. Архивировано 24 мая 2025 года.
  53. Allow AsyncMethodBuilder attribute on methods in C#. C# Tutorial. Дата обращения: 29 мая 2026. Архивировано 14 июля 2025 года.
  54. What's new in C# 13. Microsoft Learn. Дата обращения: 29 мая 2026. Архивировано 7 октября 2025 года.
  55. ref and unsafe in async and iterator methods: Unlocking Span<T> in C# 13. Dev.to. Дата обращения: 29 мая 2026. Архивировано 15 ноября 2025 года.
  56. Exploring .NET 11 Preview 1 Runtime Async: A Dive into the Future of Async in .NET. laurentkempe.com (14 февраля 2026). Дата обращения: 29 мая 2026.
  57. 1 2 [Experiment] Runtime-Async implementation. GitHub. dotnet/runtime. Дата обращения: 29 мая 2026.
  58. 1 2 C# async/await in .NET 10: The Complete Technical Guide for 2025. Dev.to. Дата обращения: 29 мая 2026.
  59. Introducing F# Asynchronous Workflows (10 октября 2007). Дата обращения: 29 мая 2026. Архивировано 22 апреля 2016 года.
  60. Asynchronous C# and F#: The key differences. tomasp.net. Дата обращения: 29 мая 2026. Архивировано 26 августа 2025 года.
  61. Asynchronous Programming in F#. Microsoft Learn. Дата обращения: 29 мая 2026. Архивировано 31 июля 2025 года.
  62. Understanding concurrency, parallelism and async/await in F#. F# for fun and profit. Дата обращения: 29 мая 2026. Архивировано 3 апреля 2025 года.
  63. Announcing F# 5. Microsoft (10 ноября 2020). Дата обращения: 29 мая 2026. Архивировано 4 августа 2025 года.
  64. 1 2 What's new in F# 6 - F#. Microsoft Learn. Дата обращения: 29 мая 2026.
  65. Task Expressions - F#. Microsoft Learn. Дата обращения: 29 мая 2026. Архивировано 29 января 2023 года.
  66. A brief history of async/await. Дата обращения: 29 мая 2026. Архивировано 3 апреля 2025 года.
  67. async: Run IO operations asynchronously and wait for their results. Hackage. Дата обращения: 29 мая 2026. Архивировано 12 августа 2025 года.
  68. Haskell and non-blocking asynchronous I/O. blog.lahteenmaki.net. Дата обращения: 29 мая 2026. Архивировано 21 мая 2025 года.
  69. 1 2 Chapter 11. Concurrent and Parallel Programming in Haskell. smunix.github.io. Дата обращения: 29 мая 2026.
  70. Control.Concurrent.Async. Hackage. Дата обращения: 29 мая 2026. Архивировано 17 июля 2025 года.
  71. The async library. FP Complete. Дата обращения: 29 мая 2026. Архивировано 25 июня 2025 года.
  72. Marlow, Simon. Parallel and Concurrent Programming in Haskell. — O'Reilly Media, 2013. — ISBN 978-1449335939.
  73. 1 2 Java-digest #29: отказ от async/await, релиз Spring Boot 3.2 и много виртуальных потоков. Growth Community. Дата обращения: 29 мая 2026.
  74. Кофе-брейк #265: асинхронное программирование на Java. JavaRush. Дата обращения: 29 мая 2026. Архивировано 9 декабря 2023 года.
  75. Асинхронные HTTP-запросы в Java: аналог async/await в C#. Skypro. Дата обращения: 29 мая 2026.
  76. Тренды в разработке 2025: II. Project Loom и No-code платформы. JavaRush (20 января 2025). Дата обращения: 29 мая 2026. Архивировано 8 сентября 2025 года.
  77. Виртуальные потоки в Java: революция в конкурентном программировании. CyberForum.ru (15 февраля 2025). Дата обращения: 3 ноября 2025. Архивировано 30 апреля 2025 года.
  78. Tascalate Async/Await. GitHub. Дата обращения: 29 мая 2026. Архивировано 26 июля 2025 года.
  79. JEP 506: Scoped Values (Final). openjdk.org. Дата обращения: 29 мая 2026.
  80. JEP 525: Structured Concurrency (Sixth Preview). openjdk.org. Дата обращения: 29 мая 2026.
  81. await - JavaScript (MDN). Дата обращения: 29 мая 2026. Архивировано 2 октября 2025 года.
  82. jQuery Core 3.0 Upgrade Guide. Дата обращения: 29 мая 2026. Архивировано 11 октября 2025 года.
  83. Асинхронные итераторы и генераторы. learn.javascript.ru. Дата обращения: 29 мая 2026. Архивировано 6 августа 2025 года.
  84. Promise.allSettled() - JavaScript. MDN Web Docs. Дата обращения: 29 мая 2026. Архивировано 15 августа 2025 года.
  85. Что нового в ECMAScript 2020 (ES11). Habr (27 января 2020). Дата обращения: 29 мая 2026.
  86. 1 2 Top-level await. v8.dev. Дата обращения: 29 мая 2026. Архивировано 30 августа 2025 года.
  87. Foundation, Node.js Node v8.0.0 (Current) - Node.js. Node.js (30 мая 2017). Дата обращения: 29 мая 2026. Архивировано 20 сентября 2025 года.
  88. 1 2 Faster async functions and promises. v8.dev (4 октября 2018). Дата обращения: 29 мая 2026. Архивировано 11 октября 2025 года.
  89. Async Stack Traces in Node.js 12. The Code Barbarian (23 мая 2019). Дата обращения: 29 мая 2026. Архивировано 3 июня 2025 года.
  90. Kotlin 1.3 is out! Kotlin Blog (29 октября 2018). Дата обращения: 29 мая 2026.
  91. async/await in Perl 5 (and ECMAScript 6). Дата обращения: 29 мая 2026. Архивировано 25 декабря 2024 года.
  92. Grant Proposal: Future::AsyncAwait. The Perl Foundation (29 октября 2018). Дата обращения: 29 мая 2026. Архивировано 14 августа 2021 года.
  93. Future::AsyncAwait - deferred subroutine syntax for futures. metacpan.org. Дата обращения: 29 мая 2026. Архивировано 26 марта 2019 года.
  94. Migrating to async/await in Perl — Part 1. Deriv. Дата обращения: 29 мая 2026.
  95. Future-AsyncAwait - metacpan.org. metacpan.org. Дата обращения: 29 мая 2026. Архивировано 2 июля 2025 года.
  96. perl-Future-AsyncAwait-0.67-1.fc42. bodhi.fedoraproject.org. Дата обращения: 29 мая 2026.
  97. Асинхронное программирование с IO::Async. Pragmatic Perl. Дата обращения: 29 мая 2026. Архивировано 9 января 2014 года.
  98. Announcing Core Async/Await. Mojolicious (26 декабря 2019). Дата обращения: 29 мая 2026. Архивировано 25 марта 2025 года.
  99. Вышел Perl 5.42.0. Habr (20 сентября 2025). Дата обращения: 29 мая 2026.
  100. Python Release Python 3.5.0. Дата обращения: 29 мая 2026. Архивировано 9 октября 2025 года.
  101. PEP 492 – Coroutines with async and await syntax. Дата обращения: 29 мая 2026. Архивировано 18 апреля 2015 года.
  102. PEP 530 – Asynchronous Comprehensions. Дата обращения: 29 мая 2026. Архивировано 20 марта 2022 года.
  103. Что нового в Python 3.6 — документация Python 3.10.0. django.fun. Дата обращения: 29 мая 2026. Архивировано 14 июля 2025 года.
  104. asyncio — Asynchronous I/O. docs.python.org. Дата обращения: 29 мая 2026.
  105. Python 3.11: новые классные возможности, которые вы можете попробовать. django.fun. Дата обращения: 29 мая 2026. Архивировано 26 марта 2025 года.
  106. Что нового в Python 3.11: TOML, TaskGroup в asyncio и группы исключений. Habr (1 августа 2022). Дата обращения: 29 мая 2026.
  107. Update Python 3.12: Is It 2 Times Faster? Key Changes. flyaps.com. Дата обращения: 29 мая 2026. Архивировано 19 мая 2025 года.
  108. What’s New In Python 3.12. docs.python.org. Дата обращения: 29 мая 2026.
  109. Python 3.12: New Features and Improvements. Analytics Vidhya (1 мая 2024). Дата обращения: 29 мая 2026. Архивировано 5 сентября 2025 года.
  110. No-GIL в Python 3.13: так ли всё радужно? Habr (20 августа 2024). Дата обращения: 29 мая 2026.
  111. What's New In Python 3.14. docs.python.org. Дата обращения: 29 мая 2026. Архивировано 20 ноября 2025 года.
  112. 1 2 Python 3.14: The 3 asyncio changes you should know about. blog.changs.co.uk. Дата обращения: 29 мая 2026.
  113. Matsakis, Niko Async-await on stable Rust! Rust Blog. Дата обращения: 29 мая 2026. Архивировано 9 сентября 2025 года.
  114. Oppermann, Philipp Async/Await. Дата обращения: 29 мая 2026. Архивировано 29 сентября 2025 года.
  115. Announcing Tokio 1.0. Tokio (23 декабря 2020). Дата обращения: 29 мая 2026. Архивировано 29 сентября 2025 года.
  116. State of Rust 2026. Dev Newsletter. Дата обращения: 29 мая 2026.
  117. Async. Corrode.dev. Дата обращения: 29 мая 2026.
  118. Announcing Rust 1.75.0. Rust Blog (28 декабря 2023). Дата обращения: 29 мая 2026.
  119. Rust 1.75.0. releases.rs (28 декабря 2023). Дата обращения: 29 мая 2026.
  120. RFC 3668: Async Closures. GitHub. Rust Language Design Team. Дата обращения: 29 мая 2026.
  121. Trait std::async_iter::AsyncIterator. doc.rust-lang.org. Дата обращения: 29 мая 2026.
  122. MCP: Low level components for async drop. GitHub. rust-lang/compiler-team. Дата обращения: 29 мая 2026.
  123. SE-0296. GitHub. Дата обращения: 29 мая 2026. Архивировано 4 декабря 2020 года.
  124. 1 2 Apple Highlights Swift Enhancements at WWDC22. The New Stack. Дата обращения: 29 мая 2026. Архивировано 29 июля 2024 года.
  125. 1 2 Что нового в Swift 5.9. Habr (20 июня 2023). Дата обращения: 29 мая 2026.
  126. Конкурентность в Swift 6: обновления, ошибки и их решения. vc.ru (12 июня 2024). Дата обращения: 29 мая 2026.
  127. WWDC 2025: Swift Concurrency становится проще и безопаснее. Habr (25 сентября 2025). Дата обращения: 29 мая 2026.
  128. WWDC 2025 Deep Dive: Mastering Swift Concurrency's Evolution Path. Dev.to. Дата обращения: 29 мая 2026.
  129. 1 2 Compiling async/await to ES3/ES5 in TypeScript. mariusschulz.com. Дата обращения: 29 мая 2026. Архивировано 7 сентября 2025 года.
  130. 1 2 3 TypeScript 4.5. TypeScript. Microsoft. Дата обращения: 29 мая 2026. Архивировано 27 сентября 2025 года.
  131. What’s new in TypeScript 4.5. LogRocket. Дата обращения: 29 мая 2026. Архивировано 14 августа 2025 года.
  132. TypeScript 4.5 Features Overview. Codetopology. Дата обращения: 29 мая 2026. Архивировано 12 августа 2024 года.
  133. TypeScript 5.2. TypeScript. Microsoft. Дата обращения: 29 мая 2026. Архивировано 7 октября 2025 года.
  134. Announcing TypeScript 5.2. TypeScript. Microsoft (24 августа 2023). Дата обращения: 29 мая 2026. Архивировано 18 сентября 2025 года.
  135. Release Notes for Zig 0.12.0. ziglang.org. Дата обращения: 29 мая 2026.
  136. Zig's New Async I/O. kristoff.it. Дата обращения: 29 мая 2026.
  137. 1 2 Asynchronous I/O in Zig. lwn.net. Дата обращения: 29 мая 2026.
  138. Async Part 3 - How the C# compiler implements async functions. Дата обращения: 29 мая 2026. Архивировано 23 июня 2025 года.
  139. 'No Bugs' Hare. Eight ways to handle non-blocking returns in message-passing programs CPPCON, 2018
  140. What Color is Your Function? Дата обращения: 29 мая 2026. Архивировано 2 октября 2025 года.
  141. Virtual Threads. Дата обращения: 29 мая 2026. Архивировано 11 октября 2025 года.
  142. Эксперимент с «зелёными потоками» в .NET провалился. Habr. Дата обращения: 29 мая 2026.

Категории