Introdução à Programação Assíncrona em PHP
\n\nO PHP tradicional funciona de forma síncrona: cada operação é executada sequencialmente. Se um script precisa enviar uma requisição HTTP ou ler um arquivo, ele espera a conclusão da operação, bloqueando a execução de todo o código. Para aplicações web de alta carga, isso se torna um gargalo. A programação assíncrona resolve esse problema, permitindo executar várias tarefas simultaneamente sem bloquear o fluxo principal.
\n\nNeste guia, vamos analisar como a assincronia funciona em PHP, quais ferramentas estão disponíveis e como usá-las na prática. Você aprenderá sobre generators, bibliotecas ReactPHP e Swoole, além dos novos recursos do PHP 8.1 — Fiber.
\n\nFundamentos da Programação Assíncrona
\n\nO que é assincronia e por que ela é necessária?
\n\nImagine que você está preparando o café da manhã. Abordagem síncrona: você coloca a chaleira no fogo, espera ferver, depois começa a fritar os ovos. Abordagem assíncrona: você coloca a chaleira e, enquanto a água aquece, prepara os ovos paralelamente. Em PHP, isso significa que, em vez de esperar a resposta de um banco de dados ou API externa, você pode executar outro código.
\n\nPrincipais vantagens da abordagem assíncrona:
\n- \n
- Aumento de desempenho em operações de I/O (rede, discos, bancos de dados) \n
- Economia de recursos do servidor — menos threads processam mais requisições \n
- Possibilidade de criar aplicações em tempo real (chats, notificações, streaming) \n
O problema do código síncrono
\n\nConsidere um exemplo clássico: obter dados de duas APIs remotas. O código síncrono será executado sequencialmente:
\n\n<?php\nfunction fetchData($url) {\n $ch = curl_init($url);\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n $result = curl_exec($ch); // Bloqueio durante a requisição\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 "Tempo: " . (microtime(true) - $start);\n?>\n\nSe cada requisição leva 2 segundos, o tempo total de execução será de 4 segundos, embora pudéssemos executar as requisições em paralelo.
\n\nFerramentas para Assincronia em PHP
\n\n1. Generators (yield) — Assincronia Leve
\n\nGenerators surgiram no PHP 5.5 e permitem criar funções que podem pausar sua execução e retornar o controle ao código chamador. Esta é a base para criar coroutines.
\n\n<?php\nfunction generator() {\n echo "Início do generator\\n";\n yield 1;\n echo "Após o primeiro yield\\n";\n yield 2;\n echo "Fim\\n";\n}\n\n$gen = generator();\nforeach ($gen as $value) {\n echo "Recebido: $value\\n";\n}\n?>\n\nGenerators podem ser usados para organizar operações não bloqueantes em conjunto com um event loop. No entanto, para assincronia completa, isso não é suficiente — é necessária uma biblioteca.
\n\n2. ReactPHP — Biblioteca Orientada a Eventos
\n\nReactPHP é uma biblioteca popular para programação assíncrona. Ela fornece um event loop, sockets não bloqueantes, cliente e servidor HTTP. Instalação via Composer:
\n\ncomposer require react/event-loop react/http\n\nExemplo de requisição HTTP assí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 recebido: " . strlen($chunk) . " bytes\\n";\n });\n $response->on('end', function () {\n echo "Requisição concluída\\n";\n });\n});\n$request->end();\n\necho "Requisição enviada, aguardando...\\n";\n$loop->run();\n?