Programación asíncrona en PHP: guía completa para principiantes

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción a la programación asíncrona en PHP

\n\n

El PHP tradicional funciona de forma síncrona: cada operación se ejecuta secuencialmente. Si un script necesita enviar una solicitud HTTP o leer un archivo, espera a que la operación termine, bloqueando la ejecución de todo el código. Para aplicaciones web con alta carga, esto se convierte en un cuello de botella. La programación asíncrona resuelve este problema, permitiendo ejecutar múltiples tareas simultáneamente sin bloquear el hilo principal.

\n\n

En esta guía, analizaremos cómo funciona la asincronía en PHP, qué herramientas están disponibles y cómo usarlas en la práctica. Aprenderá sobre generadores, las bibliotecas ReactPHP y Swoole, así como las nuevas capacidades de PHP 8.1 — Fiber.

\n\n

Fundamentos de la programación asíncrona

\n\n

¿Qué es la asincronía y por qué es necesaria?

\n\n

Imagina que estás preparando el desayuno. Enfoque síncrono: pones la tetera, esperas a que hierva, luego empiezas a freír los huevos. Enfoque asíncrono: pones la tetera y, mientras el agua se calienta, preparas los huevos revueltos en paralelo. En PHP, esto significa que, en lugar de esperar la respuesta de una base de datos o una API externa, puedes ejecutar otro código.

\n\n

Principales ventajas del enfoque asíncrono:

\n
    \n
  • Mayor rendimiento en operaciones de E/S (red, discos, bases de datos)
  • \n
  • Ahorro de recursos del servidor: menos hilos procesan más solicitudes
  • \n
  • Posibilidad de crear aplicaciones en tiempo real (chats, notificaciones, streaming)
  • \n
\n\n

El problema del código síncrono

\n\n

Consideremos un ejemplo clásico: obtener datos de dos APIs remotas. El código síncrono se ejecutará secuencialmente:

\n\n
<?php\nfunction fetchData($url) {\n    $ch = curl_init($url);\n    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n    $result = curl_exec($ch); // Bloqueo durante la solicitud\n    curl_close($ch);\n    return $result;\n}\n\n$start = microtime(true);\n$data1 = fetchData('https://api.example.com/users');\n$data2 = fetchData('https://api.example.com/posts');\necho "Tiempo: " . (microtime(true) - $start);\n?>
\n\n

Si cada solicitud toma 2 segundos, el tiempo total de ejecución será de 4 segundos, aunque podríamos ejecutar las solicitudes en paralelo.

\n\n

Herramientas para la asincronía en PHP

\n\n

1. Generadores (yield) — asincronía ligera

\n\n

Los generadores aparecieron en PHP 5.5 y permiten crear funciones que pueden pausar su ejecución y devolver el control al código que las llama. Esta es la base para crear corrutinas.

\n\n
<?php\nfunction generator() {\n    echo "Inicio del generador\\n";\n    yield 1;\n    echo "Después del primer yield\\n";\n    yield 2;\n    echo "Fin\\n";\n}\n\n$gen = generator();\nforeach ($gen as $value) {\n    echo "Recibido: $value\\n";\n}\n?>
\n\n

Los generadores se pueden usar para organizar operaciones no bloqueantes junto con un bucle de eventos. Sin embargo, para una asincronía completa, esto no es suficiente: se necesita una biblioteca.

\n\n

2. ReactPHP — biblioteca orientada a eventos

\n\n

ReactPHP es una biblioteca popular para programación asíncrona. Proporciona un bucle de eventos (Event Loop), sockets no bloqueantes, cliente y servidor HTTP. Instalación a través de Composer:

\n\n
composer require react/event-loop react/http
\n\n

Ejemplo de una solicitud HTTP asíncrona:

\n\n
<?php\nrequire 'vendor/autoload.php';\n\nuse React\\EventLoop\\Factory;\nuse React\\HttpClient\\Client;\nuse React\\HttpClient\\Response;\n\n$loop = Factory::create();\n$client = new Client($loop);\n\n$request = $client->request('GET', 'https://api.example.com/data');\n$request->on('response', function (Response $response) {\n    $response->on('data', function ($chunk) {\n        echo "Fragmento recibido: " . strlen($chunk) . " bytes\\n";\n    });\n    $response->on('end', function () {\n        echo "Solicitud completada\\n";\n    });\n});\n$request->end();\n\necho "Solicitud enviada, esperando...\\n";\n$loop->run();\n?                

Blogs

Book Recommendations