Почему для обработки промисов используют конструкции вместо console.log напрямую
Что проверяют
Понимаете ли вы, что промис это обещание значения, а не само значение. Вопрос сформулирован через JavaScript, но проверяют общее понимание асинхронности: в PHP та же ловушка воспроизводится дословно на Guzzle и ReactPHP.
Как отвечать
Печать промиса выводит объект в состоянии ожидания, а не результат: в момент вызова результата ещё нет. Значение существует только внутри обработчика или после ожидания, поэтому и нужны конструкции, а не прямой вывод.
В PHP ошибка выглядит так же: var_dump($client->getAsync($url)) покажет объект промиса. Достать значение можно двумя способами:
$promise = $client->getAsync($url);
$promise->then(
fn ($response) => $log->info((string) $response->getBody()),
fn ($reason) => $log->error((string) $reason),
);
$response = $promise->wait(); // блокирующее ожиданиеВторой смысл конструкций это ошибки. У промиса два исхода, и отклонение обрабатывается отдельной веткой: второй аргумент then либо otherwise в Guzzle, catch в ReactPHP. Необработанное отклонение всплывёт при уничтожении промиса или при wait, то есть потеряется место, где оно возникло. Файберы в современных версиях PHP и построенные на них библиотеки вроде Amp позволяют писать асинхронный код синхронно, и там работает обычный try/catch.
Третий смысл: цепочка. Результат одного шага уходит в следующий, а ошибка проскакивает мимо обработчиков успеха до первого обработчика отклонения. Прямая печать цепочки не строит и результат просто теряет.
Где спотыкаются
Логируют промис, видят объект и делают вывод, что запрос ничего не вернул. Дальше начинают искать баг в клиенте или в сети, хотя ответ ещё физически не пришёл, а обработчик к нему не привязан.
Забывают вернуть значение из обработчика. Колбэк без возврата передаёт дальше пустоту, следующий шаг цепочки получает не ответ, а null, и ошибка вылезает уже в другом месте кода.
Ставят блокирующее ожидание сразу после каждого асинхронного вызова. Десять запросов выстраиваются в очередь и выполняются последовательно, смысл асинхронности исчезает. Запускать их надо вместе, а ждать общим ожиданием пула с ограничением параллельности.