Добавить объявление

Async без await - плохая привычка, вызывающая проблемы

В коде часто можно встретить функцию, помеченную как async, хотя внутри нее нет ни одного await. Часто разработчик добавляет этот модификатор на всякий случай: вдруг потом понадобится асинхронность. Кажется, что это безобидное решение. Но на деле все меняется. И не в лучшую сторону.

Что меняется, когда функция становится async:


Как только перед функцией появляется async, она перестает возвращать значение напрямую. Вместо этого она возвращает специальный объект-обертку (Promise, Future, Task - в зависимости от языка). Даже если внутри нет ни одной асинхронной операции.

Это сразу влияет на все места, где вызывается эта функция. Теперь ее нужно вызывать с ключевым словом await. А любой код, который использует await, сам становится асинхронным. И так по цепочке вверх.

Асинхронность начинает расползаться по проекту, как снежный ком. Там, где изначально не было никакой асинхронной работы (ни сетевых запросов, ни чтения файлов, ни работы с базами данных). Зато появились лишние проблемы с вызовами.

Почему это проблема:


Главная проблема не в производительности. Современные языки хорошо оптимизируют асинхронные операции. Проблема в когнитивной нагрузке.

Когда разработчик видит функцию с async, он ожидает, что внутри происходит что-то, что требует ожидания. Сеть, диск, внешний сервис. Это подсказка, которая помогает понять, как работает код.

Если async стоит везде, где можно и где нельзя, эта подсказка перестает работать. Теряется разница между функцией, которая действительно ждет ответ от сервера, и функцией, которая просто возвращает уже готовую переменную. Код становится сложнее для чтения, отладки и поддержки.

Оправдание - а вдруг понадобится:


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

Но в прикладном коде это скорее вредит. Текущая версия функции не делает ничего асинхронного, а все ее вызывающие уже адаптированы под async. Когда реальная асинхронная операция действительно понадобится, добавить async будет делом одной минуты. А до тех пор код остается проще и понятнее.

Асинхронность - это архитектурное решение:


Async должен быть не случайной правкой, а осознанным выбором. Это маркер того, что в коде происходит что-то за пределами текущего потока выполнения: запрос к серверу, чтение файла, обращение к внешнему API.

Если таких маркеров слишком много или они стоят там, где не нужны, картина происходящего становится размытой. Трудно понять, где реальные узкие места, а где просто лишние обертки.

Простое правило:


Если внутри функции нет await - не пишите async. Это правило звучит просто, но его часто нарушают. Добавить async позже, когда он реально понадобится, несложно. А убрать его из уже существующей цепочки вызовов - гораздо сложнее.

async должен говорить о том, что происходит прямо сейчас, а не о том, что может произойти когда-нибудь.

Вывод:


Async без await - это не страховка на будущее. Это дополнительная сложность, которая распространяется по коду и делает его менее читаемым. Не стоит добавлять async, пока в этом нет реальной необходимости.

Код должен быть честным. Если функция возвращает данные синхронно - пусть она остается синхронной. А async пусть появляется только тогда, когда внутри действительно есть что-то, что требует ожидания. Это сделает код чище, а разработчикам будет проще понимать, что на самом деле происходит.
21.06.2026 54 579