Здравствуйте, друзья. Нужна помощь. Кто сможет подсказать, напишите, может вы сталкивались с такой проблемой. Вопрос заключается в следующем: мне нужно организовать асинхронные запросы к веб ресурсу через API(через синхронные запросы работает), мне нужно, чтобы между запросами была задержка несколько секунд и получал ответ от сервера. К примеру, когда я отправляю 100 http запросов, то мне нужно ждать пока все 100 не завершатся, и в конце выводится результаты этих запросов. Я хочу сделать асинхронный запрос: отправил запрос - получил ответ, задержка и потом опять запрос - ответ. Подскажите как это сделать.
//В переменную $par я передаю идентификаторы пользователей, через цикл я отправляю ///синхронные запросы
в данном цикле я добавляю в друзья вконтакте по id
foreach ( $par as $user) {
$friends = new Friends();
$friends2 = $friends -> add($token, $user, null);//добавляем в друзья
// sleep(10);
задержка не работает в синхронном запросе
...}
Сама функция добавления:
public function add( $token, $user_id, $proxy=null)
{
Я хочу сделать асинхронный запрос: отправил запрос - получил ответ, задержка и потом опять запрос - ответ.
Это не асинхронность. Поэтому забудьте о словах синхронность/асинхронность и просто опишите, что хотите сделать, что не получается, и почему вы решили, что sleep не работает.
Думаю, для асинхронности тут нужны сторонние решения. Например отличный Guzzle - Concurrent requests Guzzle
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
$client = new Client(['base_uri' => 'http://httpbin.org/']);
$promises = [
'image' => $client->getAsync('/image'),
'png' => $client->getAsync('/image/png'),
'jpeg' => $client->getAsync('/image/jpeg'),
'webp' => $client->getAsync('/image/webp')
];
// когда все запросы завершатся
// если в одном из запросов ошибка
$results = Promise\unwrap($promises);
// когда все запросы завершатся , даже если были ошибки
$results = Promise\settle($promises)->wait();
// можно получить доступ к любому результату
// function.
echo $results['image']['value']->getHeader('Content-Length')[0]
echo $results['png']['value']->getHeader('Content-Length')[0]
На клиенте можно сделать вызывая функцию с ajax-запросом через setTimeout(ajaxFunction, 1000) На сервере, используя в нужном месте sleep(1). При этом запросы посылать отдельно, а не все вместе.
Здравствуйте, Юрий. Спасибо за комментарий. А setTimeout(ajaxFunction, 1000) можно ли использовать на сервере nginx ? Просто когда я отправляю запросы то через какое то время пишет что время ожидания сервера вышло. Можете привести примерный код, как вы используете функцию sleep
mishin_stanislav, а вообще хорошей практикой будет разбить ваш запрос на много маленьких и посылать через setTimeout. В противном случае рискуете получить ошибку времени выполнения от php. Время выполнения можно настроить конечно, но лучше в эти дебри не лезть.
Не надо на сервере/бакэнде использовать sleep, это плохая практика, плюс облачные сервисы могут трактовать sleep как затраты cpu и оплачивать это придется вам как за полноценную нагрузку.
rPman, я тоже с этим столкнулся. На стороне сервера с помощью sleep просто скрипт останавливается на какое то время. А как сделать, чтобы была задержка между запросами, можно ли сделать в Guzzle задержку ?
// когда все запросы завершатся
// если в одном из запросов ошибка
$results = Promise\unwrap($promises);
// когда все запросы завершатся , даже если были ошибки
$results = Promise\settle($promises)->wait();
// можно получить доступ к любому результату
// function.
echo $results['image']['value']->getHeader('Content-Length')[0]
echo $results['png']['value']->getHeader('Content-Length')[0]
лично мне через промисы это не нравится но не важно
попробуйте использовать docs.guzzlephp.org/en/stable/request-options.html#delay
или как советуют пользователям guzzlehttp настроить таймаут и обратиться к несуществующему адресу
доберитесь до eventLoop у GuzzleHttp (он есть 100%, кажется прямо у $client) phpreact предлагает использовать addPeriodicTimer
$loop->addPeriodicTimer(10, function ()
{
echo '.';
});