Boucle d'événements du réacteur principal de ReactPHP que les bibliothèques peuvent utiliser pour les E/S événementielles.
Version de développement : cette branche contient le code de la prochaine version v3. Pour le code de la version stable v1 actuelle, consultez la branche
1.x
La prochaine version v3 sera la voie à suivre pour ce package. Cependant, nous prendrons toujours activement en charge la v1 pour ceux qui ne disposent pas encore de la dernière version. Voir également les instructions d'installation pour plus de détails.
Pour que les bibliothèques asynchrones soient interopérables, elles doivent utiliser la même boucle d'événements. Ce composant fournit une LoopInterface
commune que n'importe quelle bibliothèque peut cibler. Cela leur permet d'être utilisés dans la même boucle, avec un seul appel run()
contrôlé par l'utilisateur.
Table des matières
Exemple de démarrage rapide
Usage
courir()
arrêt()
ajouterTimer()
addPeriodicTimer()
annulerTimer()
futurTick()
ajouterSignal()
supprimerSignal()
addReadStream()
addWriteStream()
supprimerReadStream()
supprimerWriteStream()
StreamSelectLoop
ExtEventLoop
BoucleEvExt
ExtUvBoucle
Méthodes de boucle
Exécution automatique de la boucle
obtenir()
Boucle
Implémentations de boucles
Interface de boucle
Installer
Essais
Licence
Plus
Voici un serveur HTTP asynchrone construit avec uniquement la boucle d'événements.
<?phpuse ReactEventLoopLoop;require __DIR__ . '/vendor/autoload.php';$server = stream_socket_server('tcp://127.0.0.1:8080');stream_set_blocking($server, false); Loop::addReadStream($server, function ($server) {$conn = stream_socket_accept($server);$data = "HTTP/1.1 200 OKrnContent-Length: 3rnrnHin"; Loop::addWriteStream($conn, fonction ($conn) use ($data) {$écrit = fwrite($conn, $data);if ($écrit === strlen($data)) {fclose($conn ); Boucle ::removeWriteStream($conn); } else {$data = substr($data, $écrit); } }); }); Loop::addPeriodicTimer(5, function () {$memory = memory_get_usage() / 1024;$formatted = number_format($memory, 3).'K';echo "Utilisation actuelle de la mémoire : {$formatted}n"; });
Voir aussi les exemples.
Les applications typiques utiliseraient la classe Loop
pour utiliser la boucle d'événements par défaut comme ceci :
utilisez ReactEventLoopLoop;$timer = Loop::addPeriodicTimer(0.1, function () {echo 'Tick' . PHP_EOL; }); Loop::addTimer(1.0, function() utilise ($timer) { Loop::cancelTimer($timer);echo 'Terminé' . PHP_EOL; });
Comme alternative, vous pouvez également créer explicitement une instance de boucle d'événement au début, la réutiliser dans tout votre programme et enfin l'exécuter à la fin du programme comme ceci :
$loop = ReactEventLoopLoop::get();$timer = $loop->addPeriodicTimer(0.1, function () {echo 'Tick' . PHP_EOL; });$loop->addTimer(1.0, function () use ($loop, $timer) {$loop->cancelTimer($timer);echo 'Terminé' . PHP_EOL; });$loop->run();
Alors que le premier est plus concis, le second est plus explicite. Dans les deux cas, le programme effectuerait exactement les mêmes étapes.
L'instance de boucle d'événement est créée au début du programme. Cela se fait implicitement la première fois que vous appelez la classe Loop
(ou en instanciant manuellement l'une des implémentations de boucle).
La boucle d'événements est utilisée directement ou transmise en tant qu'instance au code de la bibliothèque et de l'application. Dans cet exemple, un temporisateur périodique est enregistré dans la boucle d'événements qui génère simplement Tick
chaque fraction de seconde jusqu'à ce qu'un autre temporisateur arrête le temporisateur périodique après une seconde.
La boucle d'événements est exécutée à la fin du programme. Cela se fait automatiquement lors de l'utilisation de la classe Loop
ou explicitement avec un seul appel run()
à la fin du programme.
Depuis v1.2.0
, nous vous recommandons fortement d'utiliser la classe Loop
. Les instructions de boucle explicites sont toujours valables et peuvent encore être utiles dans certaines applications, notamment pour une période de transition vers un style plus concis.
La classe Loop
existe en tant qu'accesseur global pratique pour la boucle d'événements.
La classe Loop
fournit toutes les méthodes qui existent sur LoopInterface
en tant que méthodes statiques :
courir()
arrêt()
ajouterTimer()
addPeriodicTimer()
annulerTimer()
futurTick()
ajouterSignal()
supprimerSignal()
addReadStream()
addWriteStream()
supprimerReadStream()
supprimerWriteStream()
Si vous travaillez avec la boucle d'événements dans le code de votre application, il est souvent plus simple d'interagir directement avec les méthodes statiques définies sur la classe Loop
comme ceci :
utilisez ReactEventLoopLoop;$timer = Loop::addPeriodicTimer(0.1, function () {echo 'Tick' . PHP_EOL; }); Loop::addTimer(1.0, function() utilise ($timer) { Loop::cancelTimer($timer);echo 'Terminé' . PHP_EOL; });
D'un autre côté, si vous êtes familier avec la programmation orientée objet (POO) et l'injection de dépendances (DI), vous souhaiterez peut-être injecter une instance de boucle d'événement et invoquer des méthodes d'instance sur LoopInterface
comme ceci :
utiliser ReactEventLoopLoop ; utiliser ReactEventLoopLoopInterface ; classe Greeter {boucle $privée; fonction publique __construct(LoopInterface $loop) {$this->loop = $loop; }fonction publique greet(string $name) {$this->loop->addTimer(1.0, function () use ($name) {echo 'Bonjour ' . $name . '!' . PHP_EOL; }); } }$greeter = new Greeter(Loop::get());$greeter->greet('Alice');$greeter->greet('Bob');
Chaque appel de méthode statique sera transmis tel quel à l'instance de boucle d'événement sous-jacente en utilisant l' Loop::get()
en interne. Voir LoopInterface
pour plus de détails sur les méthodes disponibles.
Lorsque vous utilisez la classe Loop
, elle exécutera automatiquement la boucle à la fin du programme. Cela signifie que l'exemple suivant planifiera une minuterie et exécutera automatiquement le programme jusqu'à ce que l'événement de minuterie se déclenche :
utilisez ReactEventLoopLoop ; Loop::addTimer(1.0, function () {echo 'Bonjour' . PHP_EOL; });
Depuis v1.2.0
, nous vous recommandons fortement d'utiliser la classe Loop
de cette manière et d'omettre tout appel explicite run()
. Pour des raisons de BC, la méthode explicite run()
est toujours valide et peut encore être utile dans certaines applications, notamment pour une période de transition vers un style plus concis.
Si vous ne souhaitez pas que la Loop
s'exécute automatiquement, vous pouvez run()
ou stop()
explicitement. Cela peut être utile si vous utilisez un gestionnaire d'exceptions global comme celui-ci :
utilisez ReactEventLoopLoop ; Loop::addTimer(10.0, function () {echo 'N'arrive jamais'; });set_exception_handler(function (Throwable $e) {echo 'Erreur : ' . $e->getMessage() . PHP_EOL; Boucle :: stop (); });lancer une nouvelle RuntimeException('Demo');
La méthode get(): LoopInterface
peut être utilisée pour obtenir l'instance de boucle d'événement actuellement active.
Cette méthode renverra toujours la même instance de boucle d'événements tout au long de la durée de vie de votre application.
utilisez ReactEventLoopLoop;utilisez ReactEventLoopLoopInterface;$loop = Loop::get();assert($loop instanceof LoopInterface);assert($loop === Loop::get());
Ceci est particulièrement utile si vous utilisez la programmation orientée objet (POO) et l'injection de dépendances (DI). Dans ce cas, vous souhaiterez peut-être injecter une instance de boucle d'événement et appeler des méthodes d'instance sur LoopInterface
comme ceci :
utiliser ReactEventLoopLoop ; utiliser ReactEventLoopLoopInterface ; classe Greeter {boucle $privée; fonction publique __construct(LoopInterface $loop) {$this->loop = $loop; }fonction publique greet(string $name) {$this->loop->addTimer(1.0, function () use ($name) {echo 'Bonjour ' . $name . '!' . PHP_EOL; }); } }$greeter = new Greeter(Loop::get());$greeter->greet('Alice');$greeter->greet('Bob');
Voir LoopInterface
pour plus de détails sur les méthodes disponibles.
En plus de LoopInterface
, un certain nombre d'implémentations de boucles d'événements sont fournies.
Toutes les boucles d'événements prennent en charge ces fonctionnalités :
Interrogation du descripteur de fichier
Minuteries ponctuelles
Minuteries périodiques
Exécution différée lors du prochain tick de boucle
Pour la plupart des utilisateurs de ce package, l'implémentation sous-jacente de la boucle d'événements est un détail d'implémentation. Vous devez utiliser la classe Loop
pour créer automatiquement une nouvelle instance.
Avancé! Si vous avez explicitement besoin d'une certaine implémentation de boucle d'événements, vous pouvez instancier manuellement l'une des classes suivantes. Notez que vous devrez peut-être d'abord installer les extensions PHP requises pour l'implémentation de la boucle d'événements respective, sinon elles lanceront une BadMethodCallException
lors de la création.
Une boucle d'événements basée sur stream_select()
.
Cela utilise la fonction stream_select()
et constitue la seule implémentation qui fonctionne immédiatement avec PHP.
Cette boucle d'événements fonctionne immédiatement sur n'importe quelle version de PHP. Cela signifie qu'aucune installation n'est requise et que cette bibliothèque fonctionne sur toutes les plateformes et versions PHP prises en charge. Par conséquent, la classe Loop
utilisera cette boucle d'événement par défaut si vous n'installez aucune des extensions de boucle d'événement répertoriées ci-dessous.
Sous le capot, il effectue un simple appel système select
. Cet appel système est limité au numéro maximum de descripteur de fichier de FD_SETSIZE
(dépendant de la plate-forme, généralement 1024) et évolue avec O(m)
( m
étant le numéro maximum de descripteur de fichier transmis). Cela signifie que vous pouvez rencontrer des problèmes lors de la gestion simultanée de milliers de flux et que vous souhaiterez peut-être envisager d'utiliser l'une des implémentations alternatives de boucles d'événements répertoriées ci-dessous dans ce cas. Si votre cas d'utilisation fait partie des nombreux cas d'utilisation courants qui impliquent de gérer seulement des dizaines ou quelques centaines de flux à la fois, alors cette implémentation de boucle d'événements fonctionne très bien.
Si vous souhaitez utiliser la gestion du signal (voir aussi addSignal()
ci-dessous), cette implémentation de boucle d'événements nécessite ext-pcntl
. Cette extension n'est disponible que pour les plates-formes de type Unix et ne prend pas en charge Windows. Il est couramment installé dans de nombreuses distributions PHP. Si cette extension est manquante (ou si vous utilisez Windows), la gestion du signal n'est pas prise en charge et lève une BadMethodCallException
à la place.
Cette boucle d'événements est connue pour s'appuyer sur l'heure de l'horloge murale pour planifier les minuteries futures lors de l'utilisation de n'importe quelle version antérieure à PHP 7.3, car une source de temps monotone n'est disponible qu'à partir de PHP 7.3 ( hrtime()
). Bien que cela n'affecte pas de nombreux cas d'utilisation courants, il s'agit d'une distinction importante pour les programmes qui s'appuient sur une précision temporelle élevée ou pour les systèmes soumis à des ajustements temporels discontinus (sauts temporels). Cela signifie que si vous programmez une minuterie pour qu'elle se déclenche dans 30 secondes sur PHP <7.3, puis ajustez l'heure de votre système en avant de 20 secondes, la minuterie peut se déclencher dans 10 secondes. Voir aussi addTimer()
pour plus de détails.
Une boucle d'événements basée sur ext-event
.
Cela utilise l'extension event
PECL, qui fournit une interface à la bibliothèque libevent
. libevent
lui-même prend en charge un certain nombre de backends spécifiques au système (epoll, kqueue).
Cette boucle est connue pour fonctionner de PHP 7.1 à PHP 8+.
Une boucle d'événements basée sur ext-ev
.
Cette boucle utilise l'extension ev
PECL, qui fournit une interface à la bibliothèque libev
. libev
lui-même prend en charge un certain nombre de backends spécifiques au système (epoll, kqueue).
Cette boucle est connue pour fonctionner de PHP 7.1 à PHP 8+.
Une boucle d'événements basée sur ext-uv
.
Cette boucle utilise l'extension uv
PECL, qui fournit une interface à la bibliothèque libuv
. libuv
elle-même prend en charge un certain nombre de backends spécifiques au système (epoll, kqueue).
Cette boucle est connue pour fonctionner de PHP 7.1 à PHP 8+.
La méthode run(): void
peut être utilisée pour exécuter la boucle d'événements jusqu'à ce qu'il n'y ait plus de tâches à effectuer.
Pour de nombreuses applications, cette méthode est la seule invocation directement visible sur la boucle d'événements. En règle générale, il est généralement recommandé de tout attacher à la même instance de boucle, puis d'exécuter la boucle une fois en bas de l'application.
$loop->run();
Cette méthode maintiendra la boucle en cours d’exécution jusqu’à ce qu’il n’y ait plus de tâches à effectuer. En d’autres termes : cette méthode bloquera jusqu’à ce que le dernier minuteur, flux et/ou signal ait été supprimé.
De même, il est impératif de s’assurer que l’application invoque effectivement cette méthode une fois. L'ajout d'écouteurs à la boucle et l'absence de l'exécution réelle entraîneront la fermeture de l'application sans réellement attendre l'un des écouteurs attachés.
Cette méthode NE DOIT PAS être appelée alors que la boucle est déjà en cours d'exécution. Cette méthode PEUT être appelée plus d'une fois après avoir été explicitement stop()
ou après son arrêt automatique car elle n'avait plus rien à faire auparavant.
La méthode stop(): void
peut être utilisée pour demander à une boucle d’événement en cours de s’arrêter.
Cette méthode est considérée comme une utilisation avancée et doit être utilisée avec précaution. En règle générale, il est généralement recommandé de laisser la boucle s'arrêter automatiquement uniquement lorsqu'elle n'a plus rien à faire.
Cette méthode peut être utilisée pour demander explicitement à la boucle d'événements de s'arrêter :
$loop->addTimer(3.0, function() use ($loop) {$loop->stop(); });
L’appel de cette méthode sur une instance de boucle qui n’est pas en cours d’exécution ou sur une instance de boucle déjà arrêtée n’a aucun effet.
La méthode addTimer(float $interval, callable $callback): TimerInterface
peut être utilisée pour mettre en file d'attente un rappel à appeler une fois après l'intervalle donné.
Le deuxième paramètre DOIT être une fonction de rappel de minuterie qui accepte l'instance de minuterie comme seul paramètre. Si vous n'utilisez pas l'instance de minuterie dans votre fonction de rappel de minuterie, vous POUVEZ utiliser une fonction qui n'a aucun paramètre.
La fonction de rappel du minuteur NE DOIT PAS lancer d' Exception
. La valeur de retour de la fonction de rappel du timer sera ignorée et n'aura aucun effet. Par conséquent, pour des raisons de performances, il est recommandé de ne pas renvoyer de structures de données excessives.
Cette méthode renvoie une instance de minuterie. La même instance de minuterie sera également transmise à la fonction de rappel de minuterie comme décrit ci-dessus. Vous pouvez appeler cancelTimer
pour annuler une minuterie en attente. Contrairement à addPeriodicTimer()
, cette méthode garantira que le rappel ne sera invoqué qu'une seule fois après l'intervalle donné.
$loop->addTimer(0.8, function () {echo 'world!' . PHP_EOL; });$loop->addTimer(0.3, function () {echo 'bonjour'; });
Voir aussi l'exemple n°1.
Si vous souhaitez accéder à des variables dans votre fonction de rappel, vous pouvez lier des données arbitraires à une fermeture de rappel comme celle-ci :
fonction bonjour($name, LoopInterface $loop) {$loop->addTimer(1.0, function () use ($name) {echo "hello $namen"; }); }bonjour('Testeur', $loop);
Cette interface n'impose aucune résolution de minuterie particulière, il faudra donc peut-être faire particulièrement attention si vous comptez sur une très haute précision avec une précision de la milliseconde ou moins. Les implémentations de boucles d'événements DEVRAIENT fonctionner au mieux et DEVRAIENT fournir une précision d'au moins la milliseconde, sauf indication contraire. De nombreuses implémentations de boucles d'événements existantes sont connues pour fournir une précision à la microseconde, mais il n'est généralement pas recommandé de s'appuyer sur cette haute précision.
De même, l'ordre d'exécution des temporisateurs programmés pour s'exécuter en même temps (dans la limite de sa précision possible) n'est pas garanti.
Cette interface suggère que les implémentations de boucles d'événements DEVRAIENT utiliser une source de temps monotone si elle est disponible. Étant donné qu'une source de temps monotone n'est disponible par défaut qu'à partir de PHP 7.3, les implémentations de boucles d'événements PEUVENT recourir à l'heure de l'horloge murale. Bien que cela n'affecte pas de nombreux cas d'utilisation courants, il s'agit d'une distinction importante pour les programmes qui s'appuient sur une précision temporelle élevée ou pour les systèmes soumis à des ajustements temporels discontinus (sauts temporels). Cela signifie que si vous programmez une minuterie pour qu'elle se déclenche dans 30 secondes, puis ajustez l'heure de votre système en avant de 20 secondes, la minuterie DEVRAIT toujours se déclencher dans 30 secondes. Voir aussi implémentations de boucles d'événements pour plus de détails.
La méthode addPeriodicTimer(float $interval, callable $callback): TimerInterface
peut être utilisée pour mettre en file d'attente un rappel à appeler à plusieurs reprises après l'intervalle donné.
Le deuxième paramètre DOIT être une fonction de rappel de minuterie qui accepte l'instance de minuterie comme seul paramètre. Si vous n'utilisez pas l'instance de minuterie dans votre fonction de rappel de minuterie, vous POUVEZ utiliser une fonction qui n'a aucun paramètre.
La fonction de rappel du minuteur NE DOIT PAS lancer d' Exception
. La valeur de retour de la fonction de rappel du timer sera ignorée et n'aura aucun effet. Par conséquent, pour des raisons de performances, il est recommandé de ne pas renvoyer de structures de données excessives.
Cette méthode renvoie une instance de minuterie. La même instance de minuterie sera également transmise à la fonction de rappel de minuterie comme décrit ci-dessus. Contrairement à addTimer()
, cette méthode garantira que le rappel sera invoqué indéfiniment après l'intervalle donné ou jusqu'à ce que vous invoquiez cancelTimer
.
$timer = $loop->addPeriodicTimer(0.1, function () {echo 'tick!' . PHP_EOL; });$loop->addTimer(1.0, function () use ($loop, $timer) {$loop->cancelTimer($timer);echo 'Terminé' . PHP_EOL; });
Voir aussi l'exemple n°2.
Si vous souhaitez limiter le nombre d'exécutions, vous pouvez lier des données arbitraires à une fermeture de rappel comme celle-ci :
fonction bonjour($name, LoopInterface $loop) {$n = 3;$loop->addPeriodicTimer(1.0, fonction ($timer) utiliser ($name, $loop, &$n) {if ($n > 0) { --$n;echo "bonjour $namen"; } else {$loop->cancelTimer($timer); } }); }bonjour('Testeur', $loop);
Cette interface n'impose aucune résolution de minuterie particulière, il faudra donc peut-être faire particulièrement attention si vous comptez sur une très haute précision avec une précision à la milliseconde ou inférieure. Les implémentations de boucles d'événements DEVRAIENT fonctionner au mieux et DEVRAIENT fournir une précision d'au moins la milliseconde, sauf indication contraire. De nombreuses implémentations de boucles d'événements existantes sont connues pour fournir une précision à la microseconde, mais il n'est généralement pas recommandé de s'appuyer sur cette haute précision.
De même, l'ordre d'exécution des temporisateurs programmés pour s'exécuter en même temps (dans la limite de sa précision possible) n'est pas garanti.
Cette interface suggère que les implémentations de boucles d'événements DEVRAIENT utiliser une source de temps monotone si elle est disponible. Étant donné qu'une source de temps monotone n'est disponible par défaut qu'à partir de PHP 7.3, les implémentations de boucles d'événements PEUVENT recourir à l'heure de l'horloge murale. Bien que cela n'affecte pas de nombreux cas d'utilisation courants, il s'agit d'une distinction importante pour les programmes qui s'appuient sur une précision temporelle élevée ou pour les systèmes soumis à des ajustements temporels discontinus (sauts temporels). Cela signifie que si vous programmez une minuterie pour qu'elle se déclenche dans 30 secondes, puis ajustez l'heure de votre système en avant de 20 secondes, la minuterie DEVRAIT toujours se déclencher dans 30 secondes. Voir aussi implémentations de boucles d'événements pour plus de détails.
De plus, les temporisateurs périodiques peuvent être sujets à une dérive du temporisateur en raison de la reprogrammation après chaque appel. En tant que tel, il n'est généralement pas recommandé de s'appuyer sur cela pour des intervalles de haute précision avec une précision à la milliseconde ou inférieure.
La méthode cancelTimer(TimerInterface $timer): void
peut être utilisée pour annuler une minuterie en attente.
Voir aussi addPeriodicTimer()
et l'exemple n°2.
L’appel de cette méthode sur une instance de timer qui n’a pas été ajoutée à cette instance de boucle ou sur une instance de timer qui a déjà été annulée n’a aucun effet.
La méthode futureTick(callable $listener): void
peut être utilisée pour planifier un rappel à appeler lors d'un prochain tick de la boucle d'événements.
Cela fonctionne de manière très similaire aux minuteries avec un intervalle de zéro seconde, mais ne nécessite pas la surcharge liée à la planification d'une file d'attente de minuterie.
La fonction de rappel de tick DOIT être capable d'accepter zéro paramètre.
La fonction de rappel tick NE DOIT PAS lancer d' Exception
. La valeur de retour de la fonction de rappel tick sera ignorée et n'aura aucun effet. Par conséquent, pour des raisons de performances, il est recommandé de ne pas renvoyer de structures de données excessives.
Si vous souhaitez accéder à des variables dans votre fonction de rappel, vous pouvez lier des données arbitraires à une fermeture de rappel comme celle-ci :
fonction bonjour($name, LoopInterface $loop) {$loop->futureTick(function () use ($name) {echo "bonjour $namen"; }); }bonjour('Testeur', $loop);
Contrairement aux minuteries, les rappels de ticks sont garantis d'être exécutés dans l'ordre dans lequel ils sont mis en file d'attente. De plus, une fois qu'un rappel est mis en file d'attente, il n'y a aucun moyen d'annuler cette opération.
Ceci est souvent utilisé pour diviser des tâches plus importantes en étapes plus petites (une forme de multitâche coopératif).
$loop->futureTick(function () {echo 'b'; });$loop->futureTick(function () {echo 'c'; });écho 'a';
Voir aussi l'exemple n°3.
La méthode addSignal(int $signal, callable $listener): void
peut être utilisée pour enregistrer un auditeur afin qu'il soit averti lorsqu'un signal a été capté par ce processus.
Ceci est utile pour capter les signaux d'interruption de l'utilisateur ou les signaux d'arrêt d'outils tels que supervisor
ou systemd
.
Le deuxième paramètre DOIT être une fonction de rappel d'écouteur qui accepte le signal comme seul paramètre. Si vous n'utilisez pas le signal dans votre fonction de rappel d'écouteur, vous POUVEZ utiliser une fonction qui n'a aucun paramètre.
La fonction de rappel de l'écouteur NE DOIT PAS lancer d' Exception
. La valeur de retour de la fonction de rappel de l'écouteur sera ignorée et n'aura aucun effet. Par conséquent, pour des raisons de performances, il est recommandé de ne pas renvoyer de structures de données excessives.
$loop->addSignal(SIGINT, function (int $signal) {echo 'Signal d'interruption utilisateur intercepté' . PHP_EOL; });
Voir aussi l'exemple n°4.
La signalisation n'est disponible que sur les plates-formes de type Unix, Windows n'est pas pris en charge en raison des limitations du système d'exploitation. Cette méthode peut lever une BadMethodCallException
si les signaux ne sont pas pris en charge sur cette plateforme, par exemple lorsque les extensions requises sont manquantes.
Remarque : Un auditeur ne peut être ajouté qu'une seule fois au même signal, toute tentative de l'ajouter plus d'une fois sera ignorée.
La méthode removeSignal(int $signal, callable $listener): void
peut être utilisée pour supprimer un écouteur de signal précédemment ajouté.
$loop->removeSignal(SIGINT, $listener);
Toute tentative de suppression d'écouteurs non enregistrés sera ignorée.
Avancé! Notez que cette API de bas niveau est considérée comme une utilisation avancée. La plupart des cas d'utilisation devraient probablement utiliser l'API Stream lisible de niveau supérieur à la place.
La méthode addReadStream(resource $stream, callable $callback): void
peut être utilisée pour enregistrer un écouteur afin d'être averti lorsqu'un flux est prêt à être lu.
Le premier paramètre DOIT être une ressource de flux valide qui prend en charge la vérification si elle est prête à être lue par cette implémentation de boucle. Une ressource de flux unique NE DOIT PAS être ajoutée plus d’une fois. Au lieu de cela, appelez d'abord removeReadStream()
ou réagissez à cet événement avec un seul écouteur, puis envoyez-le à partir de cet écouteur. Cette méthode PEUT lever une Exception
si le type de ressource donné n'est pas pris en charge par cette implémentation de boucle.
Le deuxième paramètre DOIT être une fonction de rappel d'écouteur qui accepte la ressource de flux comme seul paramètre. Si vous n'utilisez pas la ressource stream dans votre fonction de rappel d'écouteur, vous POUVEZ utiliser une fonction qui n'a aucun paramètre.
La fonction de rappel de l'écouteur NE DOIT PAS lancer d' Exception
. La valeur de retour de la fonction de rappel de l'écouteur sera ignorée et n'aura aucun effet. Par conséquent, pour des raisons de performances, il est recommandé de ne pas renvoyer de structures de données excessives.
Si vous souhaitez accéder à des variables dans votre fonction de rappel, vous pouvez lier des données arbitraires à une fermeture de rappel comme celle-ci :
$loop->addReadStream($stream, function ($stream) use ($name) {echo $name . 'dit : ' . fread($stream); });
Voir aussi l'exemple n°11.
Vous pouvez appeler removeReadStream()
pour supprimer l'écouteur d'événement de lecture pour ce flux.
L'ordre d'exécution des écouteurs lorsque plusieurs flux sont prêts en même temps n'est pas garanti.
Certaines implémentations de boucles d'événements sont connues pour déclencher l'écouteur uniquement si le flux devient lisible (déclenché par le front) et peuvent ne pas se déclencher si le flux est déjà lisible depuis le début. Cela implique également qu'un flux peut ne pas être reconnu comme lisible lorsque les données sont encore laissées dans les tampons de flux internes de PHP. En tant que tel, il est recommandé d'utiliser stream_set_read_buffer($stream, 0);
pour désactiver le tampon de lecture interne de PHP dans ce cas.
Avancé! Notez que cette API de bas niveau est considérée comme une utilisation avancée. La plupart des cas d'utilisation devraient probablement utiliser l'API Stream inscriptible de niveau supérieur à la place.
La méthode addWriteStream(resource $stream, callable $callback): void
peut être utilisée pour enregistrer un écouteur afin d'être averti lorsqu'un flux est prêt à écrire.
Le premier paramètre DOIT être une ressource de flux valide qui prend en charge la vérification si elle est prête à écrire par cette implémentation de boucle. Une ressource de flux unique NE DOIT PAS être ajoutée plus d’une fois. Au lieu de cela, appelez d'abord removeWriteStream()
ou réagissez à cet événement avec un seul écouteur, puis envoyez-le à partir de cet écouteur. Cette méthode PEUT lever une Exception
si le type de ressource donné n'est pas pris en charge par cette implémentation de boucle.
Le deuxième paramètre DOIT être une fonction de rappel d'écouteur qui accepte la ressource de flux comme seul paramètre. Si vous n'utilisez pas la ressource stream dans votre fonction de rappel d'écouteur, vous POUVEZ utiliser une fonction qui n'a aucun paramètre.
La fonction de rappel de l'écouteur NE DOIT PAS lancer d' Exception
. La valeur de retour de la fonction de rappel de l'écouteur sera ignorée et n'aura aucun effet. Par conséquent, pour des raisons de performances, il est recommandé de ne pas renvoyer de structures de données excessives.
Si vous souhaitez accéder à des variables dans votre fonction de rappel, vous pouvez lier des données arbitraires à une fermeture de rappel comme celle-ci :
$loop->addWriteStream($stream, fonction ($stream) use ($name) {fwrite($stream, 'Bonjour' . $name); });
Voir aussi l'exemple n°12.
Vous pouvez appeler removeWriteStream()
pour supprimer l'écouteur d'événement d'écriture pour ce flux.
L'ordre d'exécution des écouteurs lorsque plusieurs flux sont prêts en même temps n'est pas garanti.
La méthode removeReadStream(resource $stream): void
peut être utilisée pour supprimer l'écouteur d'événement de lecture pour le flux donné.
Supprimer de la boucle un flux qui a déjà été supprimé ou tenter de supprimer un flux qui n'a jamais été ajouté ou qui n'est pas valide n'a aucun effet.
La méthode removeWriteStream(resource $stream): void
peut être utilisée pour supprimer l'écouteur d'événement d'écriture pour le flux donné.
Supprimer de la boucle un flux qui a déjà été supprimé ou tenter de supprimer un flux qui n'a jamais été ajouté ou qui n'est pas valide n'a aucun effet.
La méthode recommandée pour installer cette bibliothèque consiste à utiliser Composer. Nouveau sur Composer ?
Une fois publié, ce projet suivra SemVer. Pour le moment, cela installera la dernière version de développement :
le compositeur nécessite une réaction/une boucle d'événement : ^ 3 @ dev
Voir également le CHANGELOG pour plus de détails sur les mises à niveau de version.
Ce projet vise à fonctionner sur n'importe quelle plate-forme et ne nécessite donc aucune extension PHP et prend en charge l'exécution sur PHP 7.1 jusqu'à PHP 8+ actuel. Il est fortement recommandé d'utiliser la dernière version de PHP prise en charge pour ce projet.
L'installation de l'une des extensions de boucle d'événements est suggérée, mais entièrement facultative. Voir aussi implémentations de boucles d'événements pour plus de détails.
Pour exécuter la suite de tests, vous devez d'abord cloner ce dépôt, puis installer toutes les dépendances via Composer :
installation du compositeur
Pour exécuter la suite de tests, accédez à la racine du projet et exécutez :
vendeur/bin/phpunit
MIT, voir fichier LICENSE.
Consultez notre composant Stream pour plus d'informations sur la façon dont les flux sont utilisés dans les applications du monde réel.
Consultez le wiki de nos utilisateurs et les dépendants de Packagist pour une liste des packages qui utilisent EventLoop dans les applications du monde réel.