Guzzle and asynchronous requests in PHP

2

I was taking a look at the GuzzleHttp documentation and saw that there is an explanation there how to use it to make asynchronous requests.

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

I did some tests exactly like the example, and did not get the expected return. The Closure that is the argument of then does not work.

How does this asynchronous request work in Guzzle ?

Is there any way to do it in PHP (as it does in Ajax), or is it another story (the concepts are different)?

    
asked by anonymous 16.12.2015 / 17:40

1 answer

3

As far as I know PHP does not support asynchronously events, precisely because it is synchronous, ie it is a request and response layer and I do not see much need to run two events at once.

On your issue, it may be the lack of wait(); , the Guzzle documentation says use is PSR-7 like this:

$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org/get');
$promise = $client->sendAsync($request)->then(function ($response) {
    echo 'I completed! ' . $response->getBody();
});
$promise->wait();
Anyway to the front-end this will be imperceptible and for the server I do not see the "advantage" of using this because the larger layer of the script will still have to wait for the events to end (when using wait(); ).

I do not know what media they use, but if you want to study the subject there is:

  

link

     

Also have reactPHP as stated here Run PHP function asynchronously

Async hack (hhvm)

In the hack (hhvm) language there are asynchronous methods:

However for the answer you will not feel changes (I believe), but in the backend it is as if it were more than one Thread and so can execute more than one task without waiting for another example (only works with <?hh ):

<?hh

namespace Hack\UserDocumentation\Async\Intro\Examples\Limtations;

async function do_cpu_work(): Awaitable<void> {
  print("Start CPU work\n");
  $a = 0;
  $b = 1;

  $list = [$a, $b];

  for ($i = 0; $i < 1000; ++$i) {
    $c = $a + $b;
    $list[] = $c;
    $a = $b;
    $b = $c;
  }
  print("End CPU work\n");
}

async function do_sleep(): Awaitable<void> {
  print("Start sleep\n");
  sleep(1);
  print("End sleep\n");
}

async function main(): Awaitable<void> {
  print("Start of main()\n");
  await \HH\Asio\v([
    do_cpu_work(),
    do_sleep(),
  ]);
  print("End of main()\n");
}

\HH\Asio\join(main());

PHP CLI

An alternative would be to execute a command as if it were in the terminal and wait for the answer, remembering async , I did this for a very specific case, where there was a script that processed consumed Apache a lot, then using exec I did something like this:

  • Windows, you should run something like:

    set QUERY_STRING="foo=1&bar=2"
    start /B cmd /S /C php -c php.ini c:/wamp/www/arquivo.php
    

    The start /B cmd /S /C is to wait for the command to finish.

  • Like-Unix, you should run something like:

     export QUERY_STRING="foo=1&bar=2";
     php -c php.ini "/etc/www/arquivo.php";
    

The whole script was like this (note I made this script some time, if it fails let me know):

function async($phpScript, $query_string='') {
    $php_exe = 'php';

    $iniFile = php_ini_loaded_file();

    if (false === $iniFile) {
        echo 'Erro ao carregar php.ini not loaded (php_ini_loaded_file = false)';
        exit;
    } else if (false === file_exists($phpScript)) {
        echo 'Script não econtrado: ' . $phpScript;
        exit;
    }

    $output = array();
    $exec = '';

    if (stripos(PHP_OS, 'WIN') !== false) {
        foreach ($_SERVER as $key => $value) {
            if ($key !== 'HTTP_ACCEPT_ENCODING' && $key !== 'QUERY_STRING') {
                $exec .= 'set ' . $key . '=' . escapeshellcmd($value) . '& ';
            }
        }

        $exec .= 'set QUERY_STRING=' . escapeshellcmd($query_string) . '& ';
        $exec .= 'start /B cmd /S /C php ' . escapeshellcmd(' -c ' . $iniFile . ' ' . $phpScript);
    } else {
        foreach ($_SERVER as $key => $value) {
            if ($key !== 'HTTP_ACCEPT_ENCODING' && $key !== 'QUERY_STRING') {
                $exec .= 'export ' . $key . '=' . escapeshellarg($value) . '; ';
            }
        }

        $exec .= 'export QUERY_STRING=' . escapeshellarg($query_string) . '; ';
        $exec .= 'php -c ' . escapeshellarg($iniFile) . ' ' .
                    escapeshellarg($phpScript);// . ' >/dev/null 2>&1 &';
    }

    exec($exec, $output, $status);

    return array(
        'status' => $status,
        'command' => $exec,
        'output'  => $output
    );
}

 export QUERY_STRING="foo=1&bar=2";
 php -c php.ini "/etc/www/arquivo.php" >/dev/null 2>&1 &

This is not very "asynchronous" for the script, but it is possible to run files that consume more memory without affecting Apache and Ngnix for example, because it runs separately, I know it is not quite what you requested, but I do not have sure what your needs really are.

    
16.12.2015 / 20:28