Обновить
6
0

Пользователь

Отправить сообщение

Пожалуй соглашусь, что описание и мой комментарий выше как-то неверно звучал.
Кажется у меня смешалось две вещи: изменение "природы" функций и возможности вызовов.

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

С точки зрения природы(кажется про неё Боб вовсе не писал) кажется все верно. Если мы вызываем в асинхронной функции синхронную, то асинхронная функция становится по сути синхронной, то есть меняется природа и по этой логике в асинхронных функциях вызывать синхронные "нельзя"(можно, но нет смысла).

Спасибо за замечание, подумаю как перефразировать в статье этот момент.

Давайте заменим в цитате "синие" на синхронные, "красные" на асинхронные.

Получим текст:

синхронные функции могут вызывать как синхронные, так и асинхронные, а асинхронные могут вызывать только асинхронные.

Если мы вызываем в синхронной функции асинхронную, то мы просто дожидаемся её результата. Если говорить про JS, то да, await вызвать нельзя, но с помощью then у Promise можно. "Природа" синхронной функции от этого не меняется. Если наоборот, то асинхронная функция перестаёт быть асинхронной, ведь ей придётся заблокироваться вызвав синхронную функцию. Соответственно "природа" асинхронной функции меняется на синхронную.

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

Я не ответил на вопрос какая стояла задача.

Задача была добавить асинхронность для http-запросов в уже существующие сервисы не сильно меняя код и архитектуру.

Вы можете поставить газзл, взять пример из статьи и убедиться, что 2 запроса будут отправлены одновременно.

У меня в статье написано следующее:

Метод sendAsync не отправляет запрос сразу, он ставит его в очередь внутри Guzzle, а уже wait берёт все запросы из очереди и отправляет их с помощью функции curl_multi_exec

Попытка объяснить «на пальцах»: Файбер приостанавливается после добавления первого запроса в очередь газзла. После этого запускается второй файбер который делает тоже самое и также приостанавливается. К этому моменту в очереди газзла 2 неотправленных запроса. После, первый файбер продолжается вызывая метод wait у первого промиса. Вызов wait запускат отправку ВСЕХ запросов, которые есть в очереди газзла, независимо от того у какого промиса этот wait вызван. В этот момент поток фактически блокируется, пока нужный промис не разрешится. Далее, когда промис разрешился файбер доходит до конца. Следом происходит продолжение выполнения второго файбера, у второго промиса также вызывается метод wait. Так как в очереди в этот момент нет запросов на отправку, метод wait либо сразу же вернет результат (если он уже готов), либо дождется пока результат нужного промиса придёт.

Вот так это работает. Вы можете сами это проверить скопировав пример метода Await::all из статьи.

Действительно, можно сделать так как вы говорите, но для решения задачи, которая перед нами стояла это не требуется. Смысл функций suspend и resume в том, чтобы приостановить файбер, а когда это сделать (после отправки запроса по сети или после постановки в очередь, но до отправки по сети) - это уже дело конкретной реализации. В нашем случае с Guzzle есть возможность сделать так как приведено, потому что Guzzle использует curl_multi_exec. Для других задач, конечно может потребоваться stream_select или что-то подобное и функция Await::all представленная в статье будет непригодна.

В примечании к функции Await::all я специально это отметил.

Конкретно это решение с Go не сравнивали, так как не было такой задачи.
Решение описанное в статье - это попытка добавить асинхронность для http-запросов в уже существующие сервисы не сильно меняя код, архитектуру и языки программирования)

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность