Как вызвать синхронную функцию из асинхронного кода?

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

Короткий ответ

Что ответить на собеседовании

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

Подробный разбор

Ответ с пояснениями

Как вызвать синхронную функцию из асинхронного кода?

  • Асинхронный код выполняет операции без блокировки потока
  • Синхронная функция завершается в текущем потоке и блокирует его на время работы
  • Внутри async синхронную функцию можно вызвать напрямую — она всё равно выполнится синхронно в рамках async-контекста
  • Если результат требуется представить как промис, его оборачивают в Promise.resolve() или используют async/await
  • Так синхронную логику можно включить в асинхронный сценарий без специальной сложной обвязки
  • В Node.js синхронные методы допустимо вызывать из async-кода, но на время выполнения они блокируют event loop
  • Долгие синхронные операции снижают производительность и отзывчивость асинхронного приложения

Итого: Синхронную функцию из асинхронного кода обычно вызывают напрямую. Если результат должен участвовать в цепочке async/await, его при необходимости оборачивают в Promise.

Подробный ответ

Основной ответ

Вызвать синхронную функцию из асинхронного кода можно напрямую, но для длительных операций это опасно блокировкой event loop. Поэтому основной практический подход — перенести синхронную функцию в отдельный поток или процесс, оставив главный поток свободным. В Python для этого обычно применяют loop.run_in_executor(): функция выполняется в отдельном потоке или процессе, не останавливая асинхронный цикл.

Ключевые моменты

  • Использование Executor: вызов asyncio.get_event_loop().run_in_executor() запускает синхронный код параллельно и сохраняет отзывчивость async-программы. По умолчанию используется ThreadPoolExecutor, однако для задач, чувствительных к GIL, можно выбрать ProcessPoolExecutor.
  • Синтаксис с await: асинхронный вызов записывают как await loop.run_in_executor(None, sync_func, *args). Это позволяет встроить синхронную функцию в async-поток без блокировки event loop.
  • Альтернативы: короткую функцию, которая практически не блокирует выполнение, можно вызвать непосредственно. Но более длительные операции создают задержки, а для тяжёлых вычислений предпочтительнее multiprocessing.

Практический контекст

В проектах на Python 3.7+ связка asyncio и run_in_executor считается стандартным способом подключать старые библиотеки и решения с синхронным интерфейсом, включая работу с файлами и сетевые вызовы в blocking mode. В React Native и Node.js используются сходные механизмы — worker threads или отдельные процессы. При правильной настройке это помогает сохранить высокий throughput и минимальную latency (~50ms или ниже).

Если потребуется, можно привести пример кода.

Практика в реальном времени

Подготовьтесь к следующему собеседованию

Interview Boost учитывает вакансию, резюме и технологии и помогает сформулировать ответ прямо во время интервью.

Начать подготовку