Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Guzzle promises asyncronously

I am attempting to use guzzle promises in order to make some http calls, to illustrate what I have, I have made this simple example where a fake http request would take 5 seconds:

$then = microtime(true);

$promise = new Promise(
    function() use (&$promise) {
        //Make a request to an http server
        $httpResponse = 200;
        sleep(5);
        $promise->resolve($httpResponse);
    });

$promise2 = new Promise(
    function() use (&$promise2) {
        //Make a request to an http server
        $httpResponse = 200;
        sleep(5);
        $promise2->resolve($httpResponse);
    });

echo 'PROMISE_1 ' . $promise->wait();
echo 'PROMISE_2 ' . $promise2->wait();

echo 'Took: ' . (microtime(true) - $then);

Now what I would want to do is start both of them, and then make both echo's await for the response. What actually happens is promise 1 fires, waits 5 seconds then fires promise 2 and waits another 5 seconds.

From my understanding I should maybe be using the ->resolve(); function of a promise to make it start, but I dont know how to pass resolve a function in which I would make an http call

like image 245
Rich Avatar asked May 23 '16 15:05

Rich


2 Answers

By using wait() you're forcing the promise to be resolved synchronously: https://github.com/guzzle/promises#synchronous-wait

According to the Guzzle FAQ you should use requestAsync() with your RESTful calls:

Can Guzzle send asynchronous requests?

Yes. You can use the requestAsync, sendAsync, getAsync, headAsync, putAsync, postAsync, deleteAsync, and patchAsync methods of a client to send an asynchronous request. The client will return a GuzzleHttp\Promise\PromiseInterface object. You can chain then functions off of the promise.

$promise = $client->requestAsync('GET', 'http://httpbin.org/get');
$promise->then(function ($response) {
echo 'Got a response! ' . $response->getStatusCode(); });

You can force an asynchronous response to complete using the wait() method of the returned promise.

$promise = $client->requestAsync('GET', 'http://httpbin.org/get');
$response = $promise->wait();
like image 149
Digital Chris Avatar answered Nov 01 '22 21:11

Digital Chris


This question is a little old but I see no answer, so I'll give it a shot, maybe someone will find it helpful.

You can use the function all($promises).

I can't find documentation about this function but you can find its implementation here.

The comment above this function starts like this:

Given an array of promises, return a promise that is fulfilled when all the items in the array are fulfilled.

Sounds like what you are looking for, so you can do something like this:

$then = microtime(true);
$promises = [];

$promises[] = new Promise(
    function() use (&$promise) {
        //Make a request to an http server
        $httpResponse = 200;
        sleep(5);
        $promise->resolve($httpResponse);
    });

$promises[] = new Promise(
    function() use (&$promise2) {
        //Make a request to an http server
        $httpResponse = 200;
        sleep(5);
        $promise2->resolve($httpResponse);
    });

all($promises)->wait();
echo 'Took: ' . (microtime(true) - $then);

If this function isn't the one that helps you solve your problem, there are other interesting functions in that file like some($count, $promises), any($promises) or settle($promises).

like image 26
vimuzumu Avatar answered Nov 01 '22 20:11

vimuzumu