> Напишите функцию, которая асинхронно сделает fetch-запрос, распарсит ответ и вернет имя пользователя (PHP)
Уровень: senior · Роль: backend · Язык: PHP · Категория: Технические вопросы
Компании: витринатв
Стек: PHP
> Пример ответа
Короткий ответ
В PHP асинхронный fetch-запрос выполняется через curl_multi или библиотеки вроде Guzzle с promise-подходом. Для простого сценария достаточно синхронного file_get_contents или curl, но если требуется именно асинхронность - используем curl_multi_init или ReactPHP. Парсинг ответа - через json_decode. Функция возвращает Promise или результат после ожидания, в зависимости от выбранного подхода.
Подробное объяснение
PHP - синхронный язык по умолчанию, поэтому "асинхронный fetch" реализуется через:
curl_multi_*- параллельные запросы без блокировки основного потока, но с ручным управлением.- Guzzle с
async()- возвращает promise, который можно резолвить черезwait()илиthen(). - ReactPHP / Amp - полноценный event loop, но это уже тяжелая зависимость.
Для задачи "сделать запрос, распарсить, вернуть имя" асинхронность оправдана только если таких запросов несколько. В противном случае синхронный curl проще и предсказуемее. В ответе на собеседовании важно показать понимание trade-off: асинхронность в PHP - это не про производительность одного запроса, а про конкурентность множества.
На практике
Для senior-позиции ожидается, что кандидат:
- объяснит, почему в PHP нет нативного
fetchкак в JS; - предложит решение через
curl_multiили Guzzle; - обработает ошибки сети, HTTP-статусы, некорректный JSON;
- покажет, как вернуть результат из асинхронной функции (callback, promise, генератор).
Если задача звучит как "напишите функцию", то в контексте PHP чаще всего подразумевают синхронную обертку с curl, потому что асинхронность без event loop не даёт выигрыша. Уточните у интервьюера, что именно он хочет: конкурентность или просто "не блокировать" - это разные вещи.
Пример кода
PHP<?php/*** Асинхронный fetch через curl_multi.* Возвращает имя пользователя из JSON-ответа.*/function fetchUserNameAsync(string $url): string{$ch = curl_init($url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_TIMEOUT, 5);$mh = curl_multi_init();curl_multi_add_handle($mh, $ch);do {$status = curl_multi_exec($mh, $active);if ($active) {curl_multi_select($mh);}} while ($active && $status === CURLM_OK);$response = curl_multi_getcontent($ch);$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);curl_multi_remove_handle($mh, $ch);curl_multi_close($mh);if ($httpCode !== 200) {throw new RuntimeException("HTTP error: $httpCode");}$data = json_decode($response, true);if (json_last_error() !== JSON_ERROR_NONE) {throw new RuntimeException('Invalid JSON');}return $data['name'] ?? throw new RuntimeException('Name not found');}// Использование:$name = fetchUserNameAsync('https://api.example.com/user/1');echo $name;
Альтернатива через Guzzle:
PHPuse GuzzleHttp\Client;function fetchUserNameAsyncGuzzle(string $url): string{$client = new Client();$promise = $client->getAsync($url)->then(function ($response) {$data = json_decode($response->getBody(), true);return $data['name'] ?? throw new RuntimeException('Name not found');});return $promise->wait();}
Как отвечать на собеседовании
Начните с уточнения: "Вы имеете в виду конкурентный запрос или просто неблокирующий?" Это покажет, что вы понимаете разницу. Затем опишите два подхода: curl_multi для параллельных запросов и Guzzle для promise-стиля. Обязательно упомяните, что в PHP нет встроенного event loop, поэтому "асинхронность" - это либо ручное управление, либо внешняя библиотека. Если интервьюер ждёт простую функцию - предложите синхронный вариант и объясните, почему он достаточен.
Что проверяет интервьюер
- Понимание модели выполнения PHP (блокирующий I/O, отсутствие нативного async/await).
- Умение работать с
curl_multiили promise-библиотеками. - Обработку ошибок: HTTP-статусы, таймауты, некорректный JSON.
- Умение объяснить trade-off между синхронным и асинхронным подходом.
- Способность выбрать правильный инструмент под задачу, а не просто "сделать асинхронно ради асинхронности".
Типичные ошибки
- Использование
file_get_contentsсstream_contextи попытка выдать это за асинхронность - это блокирующий вызов. - Игнорирование HTTP-статусов и проверки
json_decode. - Возврат
nullвместо выбрасывания исключения при ошибке. - Утверждение, что
curl_multiделает запросы "в фоне" - на самом деле он просто переключается между дескрипторами в одном потоке. - Забывают закрыть
curl_multi- утечка ресурсов. - Предложение ReactPHP без объяснения, зачем это нужно в простой задаче.
> Похожие задачи по PHP
Как изменить взаимодействие между сервисами, чтобы избежать дублирования заказов при ретраях
Как изменить взаимодействие с внешним сервисом, чтобы избежать увеличения нагрузки из-за ретраев
Что такое дедлоки?
Какие есть способы оптимизации тяжелых запросов к базе данных
> Похожие задачи по backend
Как изменить взаимодействие между сервисами, чтобы избежать дублирования заказов при ретраях
Как изменить взаимодействие с внешним сервисом, чтобы избежать увеличения нагрузки из-за ретраев
Что такое дедлоки?
Почему вы сменили PHP на Go, что было мотиватором
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью