Asynchronous queries
Thanks to the management of asynchronous query queue, you can significantly reduce query execution time. Each client object creates an individual queue.
Method for adding an asynchronous query returns a promise Promise is an object that presents a successful or failed result of completed asynchronous operation. , without waiting for actual process execution. To find out the query's result, you need to "wait" for and "deploy" a promise, or pass callback functions to it, executed on successful or unsuccessful promise completion.
Simple objective: pass a series of queries and process their results. You can request a client to independently process the queue and return all responses. Responses will be sorted as per received response time (may not match to sequence of queries):
use Bitrix\Main\Web\HttpClient; use Bitrix\Main\Web\Uri; use Bitrix\Main\Web\Http\Request; use Bitrix\Main\Web\Http\Method; use Bitrix\Main\Web\Http\ClientException; $http = new HttpClient(); $urls = [ 'http://www.flowersweb.info/images/t/top1.jpg', 'http://bitrix24.eu', 'https://www.bitrix24.com/', ]; foreach ($urls as $url) { $request = new Request(Method::GET, new Uri($url)); $http->sendAsyncRequest($request); } try { foreach ($http->wait() as $response) { var_dump($response->getStatusCode()); } } catch (ClientException $e) { var_dump($e->getMessage()); }
If you need a more strict control, including for sequence of responses, you have to use promises:
use Bitrix\Main\Web\HttpClient; use Bitrix\Main\Web\Uri; use Bitrix\Main\Web\Http\Request; use Bitrix\Main\Web\Http\Method; use Bitrix\Main\Web\Http\ClientException; $http = new HttpClient(); $urls = [ 'http://www.flowersweb.info/images/t/top1.jpg', 'http://bitrix24.eu', 'https://www.bitrix24.com/', ]; $promises = []; // add queries to the queue foreach ($urls as $url) { $request = new Request(Method::GET, new Uri($url)); $promises[] = $http->sendAsyncRequest($request); } // execute promises foreach ($promises as $promise) { try { $response = $promise->wait(); var_dump($promise->getRequest()->getUri()->getHost()); var_dump($response->getStatusCode()); } catch (ClientException $e) { var_dump($e->getMessage()); } }
Also, you can pass two callback functions to the promise method then
: on successfully completed promise and for an error instance. You can organize chains from callback functions, by sequentially calling then
.
Callback function for a successfully completed promise receives a response object ResponseInterface and must return a response object. Callback function for an error receives an exception ClientException and must return or throw an exception.
use Bitrix\Main\Web\HttpClient; use Bitrix\Main\Web\Uri; use Bitrix\Main\Web\Http\Request; use Bitrix\Main\Web\Http\Method; $http = new HttpClient(); $urls = [ 'http://www.flowersweb.info/images/t/top1.jpg', 'http://bitrix24.eu', 'https://www.bitrix24.com/', ]; // add queries to the queue foreach ($urls as $url) { $request = new Request(Method::GET, new Uri($url)); $promise = $http->sendAsyncRequest($request); // callback $promise->then(function ($response) use ($promise) { var_dump($promise->getRequest()->getUri()->getHost()); var_dump($response->getStatusCode()); return $response; }); } // execute promises $http->wait();
If you won't directly call queue processing (string $http->wait();
), this will be done via kernel's background jobs. Callback functions will be called, but you won't be able to view their result at the screen due to background jobs being executed after fetching of content. You can use this in case you don't need to show retrieved results for processed queues: content is loaded to users quicker than queries will be executed at the background (you need to replace var_dump()
to AddMessage2Log()
in the example).