Tapahtumasilmukat ReactPHP:llä
Suorittakaa ei-blokkaavaa I/O:ta ReactPHP:n tapahtumasilmukalla.
Tapahtumasilmukat ReactPHP:llä on ilmainen PHP Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu PHP Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. PHP Academy-kurssilla on yhteensä 4 oppituntia.
ReactPHP yhdellä lauseella
ReactPHP on puhdas-PHP:hen perustuva, riippuvuuksista riippumaton työkalupakki ei-blokkaavaan I/O:hon. Se rakentuu yhden tapahtumasilmukan ympärille. Laajennusta ei tarvita — se toimii perus-PHP:llä käyttäen stream_select-toimintoa tai sen ollessa saatavilla ext-event/ext-ev-laajennusta. Sen avulla voitte kirjoittaa pitkäkestoisia palvelimia, samanaikaisia HTTP-asiakkaita ja suoratoistoputkia tavallisella PHP:llä.
Globaali silmukka
ReactPHP:n nykyaikaiset versiot (v1.2+) tarjoavat oletussilmukan staattisen React\EventLoop\Loop-julkisivun kautta — silmukkaa ei tarvitse välittää kaikkialle erikseen. Ajastakaa takaisinkutsu ajastimella; silmukka suoritetaan, kunnes sillä ei ole enää tehtävää.
<?php
require 'vendor/autoload.php';
use React\EventLoop\Loop;
Loop::addTimer(1.0, function () {
echo "fired after 1 second\n";
});
echo "scheduled\n";
// Loop::run() is auto-invoked at script shutdown in v1.2+Ajastimet ja toistuva työ
Ei-blokkaava ajoitus korvaa sleep()-kutsun. addTimer suoritetaan kerran; addPeriodicTimer toistetaan. Kumman tahansa voi peruuttaa pysäyttääkseen sen. Koska nämä ohjautuvat silmukasta, muut tehtävät jatkavat suoritustaan ajastimen odottaessa.
<?php
use React\EventLoop\Loop;
$count = 0;
$timer = Loop::addPeriodicTimer(0.5, function () use (&$count, &$timer) {
echo 'tick ' . (++$count) . "\n";
if ($count === 4) {
Loop::cancelTimer($timer); // stop after 4 ticks
}
});Promiset asynkronisille tuloksille
ReactPHP palauttaa promisen jokaisesta myöhemmin valmistuvasta toiminnosta. Liittäkää kohtaan then() onnistumisen käsittelevä takaisinkutsu ja toinen takaisinkutsu epäonnistumisen käsittelyä varten. Promiset voidaan yhdistää, joten voitte muuntaa ja ketjuttaa tuloksia ilman syvälle sisäkkäisiä takaisinkutsuja.
<?php
use React\Promise\Promise;
function asyncDouble(int $n): Promise {
return new Promise(function ($resolve) use ($n) {
\React\EventLoop\Loop::addTimer(0.1, fn() => $resolve($n * 2));
});
}
asyncDouble(21)
->then(fn($r) => printf("result: %d\n", $r)) // 42
->catch(fn(\Throwable $e) => printf("err: %s\n", $e->getMessage()));Samanaikaiset HTTP-pyynnöt asynkronisella asiakkaalla
Suurin hyöty on se, että voitte lähettää monia HTTP-pyyntöjä samanaikaisesti yhdestä säikeestä. React\Http\Browser palauttaa promiseja; React\Promise\all() odottaa koko erän valmistumista. Kymmenen yhden sekunnin pyyntöä valmistuu noin sekunnissa, ei kymmenessä.
<?php
use React\Http\Browser;
use function React\Promise\all;
$browser = new Browser();
$urls = [
'https://httpbin.org/delay/1',
'https://httpbin.org/delay/1',
'https://httpbin.org/delay/1',
];
$requests = array_map(fn($u) => $browser->get($u), $urls);
all($requests)->then(function (array $responses) {
echo 'all done: ' . count($responses) . " responses\n";
});Fibers tekevät koodista synkronisen näköistä
Takaisinkutsuketjuista tulee hankalia. ReactPHP integroituu react/async-pakettiin, joka käyttää PHP 8.1:n Fibers-ominaisuutta, joten voitte odottaa promisea kohdassa await() ja kirjoittaa suoraviivaista koodia. coroutine()/async()-kääre suorittaa funktion fiberin sisällä.
<?php
use function React\Async\async;
use function React\Async\await;
use React\Http\Browser;
$main = async(function () {
$browser = new Browser();
$a = await($browser->get('https://httpbin.org/uuid'));
$b = await($browser->get('https://httpbin.org/uuid'));
echo (string) $a->getBody();
echo (string) $b->getBody();
});
$main();Ei-blokkaava TCP-palvelin
ReactPHP on parhaimmillaan palvelimissa. SocketServer hyväksyy yhteyksiä ja tuottaa tapahtumia; jokainen yhteys on itsessään ei-blokkaava stream. Yksi prosessi käsittelee tuhansia samanaikaisia asiakkaita.
<?php
use React\Socket\SocketServer;
use React\Socket\ConnectionInterface;
$socket = new SocketServer('127.0.0.1:8080');
$socket->on('connection', function (ConnectionInterface $conn) {
$conn->write("Welcome\n");
$conn->on('data', function ($data) use ($conn) {
$conn->write('echo: ' . $data); // streamed back, non-blocking
});
});
echo "listening on 127.0.0.1:8080\n";HTTP-palvelin muutamalla rivillä
react/http-palvelin käsittelee pyynnöt takaisinkutsulla, joka palauttaa Response-olion tai sellaisen palauttavan promisen. Koska kyseessä on pitkäkestoinen prosessi, riippuvuudet alustetaan kerran — mutta vastaatte myös muistin hallinnasta pyyntöjen välillä.
<?php
use React\Http\HttpServer;
use React\Http\Message\Response;
use Psr\Http\Message\ServerRequestInterface;
use React\Socket\SocketServer;
$http = new HttpServer(function (ServerRequestInterface $request) {
return Response::json(['path' => $request->getUri()->getPath()]);
});
$http->listen(new SocketServer('0.0.0.0:8000'));
echo "http://0.0.0.0:8000\n";Suoratoisto ilman puskurointia
ReactPHP:n streamit toteuttavat vastapaineen hallinnan: voitte yhdistää luettavan streamin kirjoitettavaan kohdassa pipe(), ja ajonaikainen ympäristö rajoittaa nopeutta automaattisesti. Näin gigatavuja voidaan siirtää käyttäen jatkuvasti pientä ja vakiokokoista muistimäärää sen sijaan, että tiedostot ladattaisiin RAM-muistiin.
<?php
use React\Stream\ReadableResourceStream;
use React\Stream\WritableResourceStream;
$source = new ReadableResourceStream(fopen('big.log', 'r'));
$dest = new WritableResourceStream(fopen('php://stdout', 'w'));
$source->pipe($dest); // back-pressure aware, never buffers whole fileKuolemansynti: silmukan blokkaaminen
Kaikki pysähtyy heti, kun kutsutte käsittelijässä blokkaavaa funktiota — esimerkiksi sleep()-kutsua, blokkaavaa PDO-kutsua, curl_exec-kutsua tai URL-osoitteen käsittelevää file_get_contents-kutsua. Ne jäädyttävät yhden säikeen ja pysäyttävät kaikki yhteydet. Käyttäkää ReactPHP:n vastineita: viiveisiin Loop::addTimer-kutsua, kyselyihin clue/reactphp-*-pakettia tai asynkronisia tietokanta-ajureita ja HTTP-pyyntöihin Browser-asiakasta.
<?php
use React\EventLoop\Loop;
use function React\Async\await;
use React\Promise\Deferred;
// BAD: sleep(2); // freezes the entire loop
// GOOD: async delay that yields control
function delay(float $s): \React\Promise\PromiseInterface {
$d = new Deferred();
Loop::addTimer($s, fn() => $d->resolve(null));
return $d->promise();
}
// await(delay(2.0)); // inside a fiber/coroutineSamanaikaisuuden rajoittaminen
Rajoittamaton fan-out voi kuluttaa tiedostokuvaajat loppuun tai kuormittaa liikaa taustalla olevaa API:a. ReactPHP:n clue/mq-react jonottaa työt ja rajoittaa samanaikaisuuden käsittelemällä N:ää promisea kerrallaan muiden odottaessa. Tämä rajoittaa oman ulospäin suuntautuvan kuormituksen määrää.
<?php
use Clue\React\Mq\Queue;
use React\Http\Browser;
$browser = new Browser();
// At most 10 in-flight requests across 1000 URLs
$q = new Queue(10, null, fn($url) => $browser->get($url));
$promises = array_map(fn($u) => $q($u), $thousandUrls ?? []);
\React\Promise\all($promises)->then(function ($responses) {
echo 'completed ' . count($responses) . " with cap of 10\n";
});Pikatarkistus
Miten ReactPHP-käsittelijässä odotetaan 2 sekuntia heikentämättä samanaikaisuutta?
Kertaus
ReactPHP tuo ei-blokkaavan I/O:n tavalliseen PHP:hen:
- Yksi tapahtumasilmukka (
Loop-fasadi) ohjaa ajastimia, socket-yhteyksiä ja streameja — laajennusta ei tarvita. - Operaatiot palauttavat promiseja;
all()suorittaa pyynnöt rinnakkain, jareact/asyncsekä Fibers mahdollistavatawait()-kutsun synkroniselta näyttävässä koodissa. - Rakentakaa pitkäikäisiä TCP/HTTP-palvelimia ja backpressurea käyttäviä streameja, jotka käsittelevät tuhansia yhteyksiä prosessia kohden.
- Silmukkaa ei saa koskaan blokata —
sleep/blokkaava I/O on korvattava Reactin ajastimilla ja async-ajureilla.
Opi PHP tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 49
- Oppitunnit
- 195
Usein kysytyt kysymykset
Onko oppitunti ”Tapahtumasilmukat ReactPHP:llä” ilmainen?
Kyllä – oppitunnin ”Tapahtumasilmukat ReactPHP:llä” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko PHP Academy-kurssin, päivitä CoddyKit PROhon. PHP Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Tapahtumasilmukat ReactPHP:llä”?
Suorittakaa ei-blokkaavaa I/O:ta ReactPHP:n tapahtumasilmukalla. Harjoittelet PHP Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni PHP Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin PHP Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.
Kuinka kauan ”Tapahtumasilmukat ReactPHP:llä”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä PHP Academy-oppitunnilla?
Kyllä. Jokainen PHP Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- PHP:n samanaikaisuusmalli
- PHP 8.1 Fibers
- Tapahtumasilmukat ReactPHP:llä
- Tehokkaat palvelimet Swoolella