¿Cómo hacer requests HTTP asíncronas en PHP?

La solicitud HTTP asíncrona nos ayuda a procesar requests HTTP usando entrada o salida sin bloqueo, en diferentes subprocesos. Algunos se refieren a esto como capacidades COMET. El uso principal de las requests HTTP asíncronas es cuando el cliente solicita al servidor una respuesta tardía. Un ejemplo común es un cliente de chat AJAX donde empujamos o extraemos tanto del cliente como del servidor. Estos escenarios bloquean al cliente durante mucho tiempo en el socket del servidor esperando un nuevo mensaje. 

PHP atiende las requests de forma síncrona. Significa que cada línea de código se ejecuta de la manera síncrona del script. Después de obtener el resultado de una línea, ejecuta la siguiente línea o espera el resultado antes de saltar a la ejecución de la siguiente línea de código. Hay casos en los que se supone que debemos realizar requests a las URL y no dependen entre sí. En este escenario, no queremos esperar el resultado de una solicitud para ejecutar otras requests. Por lo tanto, hacemos requests asincrónicas.

Guzzle 6: Guzzle es un cliente PHP HTTP que ayuda a enviar requests HTTP. Estos métodos se pueden usar para enviar requests HTTP asíncronas.

  • SolicitudAsync,
  • SendAsync,
  • obtener asíncrono,
  • HeadAsync,
  • PutAsync,
  • PostAsync,
  • EliminarAsync,
  • patchAsync

Descargue el paquete Guzzle php. Se puede instalar a través de composer.

php composer.phar require guzzlehttp/guzzle:~6.0

o

composer require guzzlehttp/guzzle:~6.0

Incluya el archivo de «carga automática» en la parte del script del código para que cargue todas las clases y métodos.

PHP

<?php
 
require_once(__DIR__ . '/vendor/autoload.php');
$client = new GuzzleHttp\Client();
 
$promises = [
    $client->getAsync('http://localhost')
            ->then(function ($response)
    { echo '10'; }),
    
    $client->getAsync('http://www.google.com')
            ->then(function ($response)
    { echo '20'; }),
     
    $client->getAsync('http://localhost')
            ->then(function ($response)
    { echo '30'; }),
     
    $client->getAsync('http://localhost')
            ->then(function ($response)
    { echo '40'; }),
     
    $client->getAsync('http://localhost')
            ->then(function ($response)
    { echo '50'; }),
     
    $client->getAsync('http://localhost')
            ->then(function ($response)
    { echo '60'; }),
     
    $client->getAsync('http://localhost')
            ->then(function ($response)
   { echo '70'; }),
];
 
$results = GuzzleHttp\Promise\unwrap($promises);
 
// Please wait for a while to complete
// the requests(some of them may fail)
$results = GuzzleHttp\Promise\settle(
        $promises)->wait();
         
print "finish/over." . PHP_EOL;
?>

En el código anterior, se incluye el archivo de «carga automática», y luego se crea el objeto de cliente Guzzle Http que se almacena en la variable «cliente» y para cada solicitud Http se usa el método getAsync() con la URL. La solicitud que obtenga la primera respuesta imprimirá el número. No importará el orden de la solicitud.

Requests HTTP asíncronas usando Promise: un solo resultado de una operación asíncrona representa una Promise . Las requests asíncronas se utilizan para no bloquear las operaciones HTTP. Cuando las requests HTTP asíncronas envían una promesa, se devuelve.

Ejecute una solicitud usando HTTPlug:

$request = $messageFactory->createRequest(
    'GET', 'http://php-http.org');
$promise = $client->sendAsyncRequest($request);
echo  'Non-blocking!';

Espera: la «promesa» que se devuelve de lo anterior, implementa http\Promise\Promise . La respuesta aún no se conoce durante este punto de tiempo. Espera a que llegue esa respuesta.

try {
  $response = $promise->wait();
} catch (\Exception $exception) {
  echo $exception->getMessage();
}  

Entonces: en lugar de esperar, podemos realizar pasos de forma asíncrona. Llame al método entonces con dos argumentos.

  1. Una devolución de llamada que se ejecutará si la solicitud resulta exitosa.
  2. Devolución de llamada que se ejecutará si la solicitud da como resultado un error.
  
// Success Callback
function (ResponseInterface $response) {
    
    echo 'New response!';

    // Write status code to the log file
    file_put_contents('responses.log', 
        $response->getStatusCode() . "\n", FILE_APPEND);
    return $response;
},

// Failure Callback
function (\Exception $exception) {
    echo 'We have a problem';
    throw $exception;
}

Concurrencia en Promesa: Concurrencia significa múltiples cálculos que tienen lugar al mismo tiempo. Es bueno cuando nos ocupamos de una gran cantidad de requests al mismo tiempo. Para la concurrencia, debemos usar la clase «EachPromise» y el generador de rendimiento y, por último, agregar wait() al final del programa.

PHP

<?php
 
use GuzzleHttp\Promise\EachPromise;
use GuzzleHttp\Psr7\Response;
  
$users = ['one', 'two', 'three'];
  
$promises = (function () use ($users) {
    foreach ($users as $user) {
         
        // Using generator
        yield $this->getAsync(
   'https://api.demo.com/v1/users?username='
        . $user);       
    }
})();
  
$eachPromise = new EachPromise($promises, [
     
    // Number of concurrency
    'concurrency' => 4,
    'fulfilled' => function (Response $response) {
        if ($response->getStatusCode() == 200) {
            $user = json_decode(
                $response->getBody(), true);
             
            // processing response of the user
        }
    },
     
    'rejected' => function ($reason) {
    // handle promise rejected
    }
]);
  
$eachPromise->promise()->wait();
?>

Creación de una solicitud cURL de subprocesos múltiples: en general, podemos manejar varias requests. Primero activamos el primero y procesamos la respuesta, luego el segundo y el tercero, y así sucesivamente. Pero, este proceso es lento y requiere mucho tiempo. Pero cURL ofrece las funciones curl_multi_* para manejar cualquier solicitud asíncrona.

$running = null;
$mh = curl_multi_init();

$ch1 = curl_init();
curl_setopt($ch1, CURLOPT_URL, 'https://endpoint.com');

// Other curl options....
curl_multi_add_handle($mh, $ch1);

$ch2 = curl_init();
curl_setopt($ch2, CURLOPT_URL, 'https://endpoint.com');

// Other curl options....  
curl_multi_add_handle($mh, $ch2);

do {
   curl_multi_exec($mh, $running);
   curl_multi_select($mh);
} while ($running > 0);

$r1 = curl_multi_getcontent($ch1);
$r2 = curl_multi_getcontent($ch2);
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);

Las respuestas se recogen en las variables “r1” y “r2”. Con la ayuda de estas funciones de cURL, podemos activar requests en paralelo para ahorrar tiempo y procesar las respuestas más rápido.

Publicación traducida automáticamente

Artículo escrito por sharmaanushka y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *