Maison >interface Web >js tutoriel >Comment utiliser des événements de serveur dans Node.js

Comment utiliser des événements de serveur dans Node.js

Joseph Gordon-Levitt
Joseph Gordon-Levittoriginal
2025-02-08 09:31:09237parcourir

How to Use Server-sent Events in Node.js

Points de base

  • Le serveur Send Events (SSE) permet au serveur de pousser les données au navigateur à tout moment, permettant des fonctions telles que des rapports d'actualités en temps réel, des prévisions météorologiques et des cours des actions. Le navigateur émet une demande initiale pour établir une connexion et le serveur garde la connexion ouverte pour envoyer un SMS.
  • SSE est plus simple que WebSockets, utilise HTTP standard, prend en charge la communication à sens unique et fournit une reconnexion automatique. Le serveur peut résilier la réponse SSE à tout moment, mais si la connexion est interrompue, le navigateur tentera automatiquement de se reconnecter.
  • Le serveur peut fournir un certain nombre d'URL de canal SSE ou une URL de point de terminaison unique. Les messages du serveur peuvent avoir des événements associés pour identifier un type particulier d'informations. Le serveur peut également envoyer un ID après la ligne de données pour renvoyer tous les messages manqués lorsque la connexion est déconnectée.
  • Le navigateur peut terminer la communication SSE à l'aide de la méthode .close () de l'objet Eventsource. Le serveur peut résilier la connexion en déclenchant Res.end () ou en envoyant un délai de réessayer, puis en renvoyant un statut HTTP 204 lorsque le même navigateur essaie de se reconnecter. Seuls les navigateurs peuvent rétablir la connexion en créant un nouvel objet Eventsource.

Cet article explorera comment utiliser le serveur Send Events (SSE) pour permettre aux clients de recevoir des mises à jour automatiques du serveur via une connexion HTTP. Nous explorerons également son utilisation et montrerons une démonstration pratique de la façon d'utiliser Node.js pour envoyer des événements à l'aide d'un serveur.

  • Avantages de l'envoi du serveur
  • Démarrage rapide du serveur Envoyer des événements
    • Conseils importants
  • Événement d'envoi de serveur avancé
    • canaux SSE simples et multiples
    • Envoyez différentes données sur un seul canal
    • Utilisation de l'identifiant de données
    • Spécifiez Retry Delay
    • d'autres gestionnaires d'événements
    • terminer la communication SSE
  • Conclusion

Avantages des événements d'envoi de serveur

Web répond aux messages HTTP en fonction de la demande de demande. Votre navigateur émet une demande d'URL et le serveur renvoie les données. Cela peut amener le navigateur à faire plus de demandes aux images, CSS, JavaScript, etc., et le serveur répond. Le serveur ne peut pas envoyer activement de messages au navigateur, alors comment indique-t-il que les données ont été modifiées? Heureusement, vous pouvez utiliser Server Send Events (SSE) pour ajouter des fonctionnalités telles que les communiqués de presse en direct, les prévisions météorologiques et les cours des actions.

Il a toujours été possible d'utiliser des technologies Web standard pour réaliser des mises à jour de données en temps réel:

    Le Web des années 1990 a actualisé à l'aide de la page complète ou du cadre / iframe.
  • Le Web des années 2000 a introduit Ajax, qui peut utiliser un sondage long pour demander des données et mettre à jour les éléments DOM correspondants avec de nouvelles informations.
Aucune de ces options n'est idéale car le navigateur doit déclencher un rafraîchissement. S'il fait des demandes trop souvent, il n'y aura pas de modifications de données, donc le navigateur et le serveur feront un travail inutile. S'il demande trop lentement, il peut manquer des mises à jour importantes et le cours de l'action que vous suivez a chuté!

Le serveur Send Events (SSE) permet au serveur de pousser les données au navigateur à tout moment:

  • Le navigateur fait toujours une demande initiale pour établir la connexion.
  • Le serveur renvoie une réponse de flux d'événements et maintient la connexion ouverte.
  • Le serveur peut utiliser cette connexion pour envoyer des messages texte à tout moment.
  • Les données entrantes augmenteront un événement JavaScript dans le navigateur. La fonction du gestionnaire d'événements analyse les données et met à jour le DOM.

Essentiellement, SSE est un flux de données illimité. Considérez-le comme le téléchargement d'un fichier infiniment grand téléchargé en petits morceaux que vous pouvez intercepter et lire.

SSE a été initialement mis en œuvre en 2006 et prend en charge cette norme dans tous les principaux navigateurs. Il n'est peut-être pas bien connu sous le nom de WebSockets, mais le serveur envoie des événements plus faciles, utilise HTTP standard, prend en charge la communication unidirectionnelle et fournit une reconnexion automatique. Ce tutoriel fournit un exemple de code Node.js sans modules tiers, mais SSE peut être utilisé dans d'autres langages côté serveur, y compris PHP.

Démarrage rapide du serveur Envoyer des événements

La démonstration suivante implémente un serveur Web Node.js qui publie des nombres aléatoires entre 1 et 1000 à des intervalles aléatoires d'au moins toutes les trois secondes.

Vous pouvez trouver notre démo Node.js SSE ici.

Ce code utilise les modules standard Node.js HTTP et URL pour créer un serveur Web et analyser URL:

<code class="language-javascript">import http from "node:http";
import url from "node:url";</code>

Le serveur vérifie les demandes et réagit de l'URL entrantes lors de la rencontre du chemin / chemin aléatoire:

<code class="language-javascript">const port = 8000;

http.createServer(async (req, res) => {

  // 获取 URI 路径
  const uri = url.parse(req.url).pathname;

  // 返回响应
  switch (uri) {
    case "/random":
      sseStart(res);
      sseRandom(res);
      break;
  }

}).listen(port);

console.log(`server running: http://localhost:${port}\n\n`);</code>

Il répond initialement avec l'en-tête du flux d'événements SSE HTTP:

<code class="language-javascript">// SSE 头
function sseStart(res) {
  res.writeHead(200, {
    Content-Type: "text/event-stream",
    Cache-Control: "no-cache",
    Connection: "keep-alive"
  });
}</code>

Une autre fonction envoie ensuite un nombre aléatoire et s'appelle après que l'intervalle aléatoire passe:

<code class="language-javascript">// SSE 随机数
function sseRandom(res) {
  res.write("data: " + (Math.floor(Math.random() * 1000) + 1) + "\n\n");
  setTimeout(() => sseRandom(res), Math.random() * 3000);
}</code>

Si vous exécutez votre code localement, vous pouvez utiliser Curl dans votre terminal pour tester la réponse:

<code class="language-bash">$> curl -H Accept:text/event-stream http://localhost:8000/random
data: 481

data: 127

data: 975</code>

Appuyez sur Ctrl | CMD et C pour mettre fin à la demande.

Le client du navigateur JavaScript se connecte à / aléatoire URI à l'aide du constructeur d'objets Eventsource:

<code class="language-javascript">// 客户端 JS
const source = new EventSource("/random");</code>

Les données entrantes déclenchent le gestionnaire d'événements du message, où les données: la chaîne après elle est disponible dans la propriété .data de l'objet de l'événement:

<code class="language-javascript">source.addEventListener('message', e => {
  console.log('RECEIVED', e.data);
});</code>

Conseils importants

  • comme fetch (), le navigateur émet des demandes HTTP standard, vous devrez donc peut-être gérer CSP, CORS et avoir la possibilité de passer un deuxième paramètre { withCredentials: true } au constructeur Eventsource pour envoyer un cookie.
  • Le serveur doit conserver un objet de réponse RES distinct pour chaque utilisateur connecté pour lui envoyer des données. Ceci est réalisé dans le code ci-dessus en passant la valeur à la fermeture pour l'appel suivant.
  • Les données de message ne peuvent être qu'une chaîne dans les données de format: nn (probablement JSON). Il est crucial de résilier le retour du chariot.
  • Le serveur peut résilier la réponse SSE à tout moment en utilisant res.end (), mais ...
  • Lorsque la connexion est interrompue, le navigateur essaie automatiquement de se reconnecter;

Advanced Server envoie des événements

SSE ne nécessite pas plus de code que ci-dessus, mais les sections suivantes discutent d'autres options.

canaux SSE simples et multiples

Le serveur peut fournir un certain nombre d'URL de canal SSE. Par exemple:

  • / dernier / news
  • / dernier / météo
  • / le dernier / stockprice

Cela peut être pratique si une seule page affiche un sujet, mais pas si une seule page montre des nouvelles, des conditions météorologiques et des cours des actions. Dans ce cas, le serveur doit maintenir trois connexions pour chaque utilisateur, ce qui peut entraîner des problèmes de mémoire à mesure que le trafic augmente.

Une autre option consiste à fournir une URL de point de terminaison unique, telle que / dernier, qui envoie n'importe quel type de données sur un canal de communication. Le navigateur peut indiquer le sujet d'intérêt dans la chaîne de requête URL, tel que / le dernier? Type = News, Weather, Stockprice, afin que le serveur puisse limiter la réponse SSE à un message spécifique.

Envoyez différentes données sur un seul canal

Les messages du serveur peuvent avoir un event: associé qui est passé au-dessus de la ligne data: pour identifier un type d'information spécifique:

<code class="language-javascript">import http from "node:http";
import url from "node:url";</code>

Celles-ci ne déclenchent pas le gestionnaire d'événements "Message" du client. Vous devez ajouter un gestionnaire pour chaque type d'événement. Par exemple:

<code class="language-javascript">const port = 8000;

http.createServer(async (req, res) => {

  // 获取 URI 路径
  const uri = url.parse(req.url).pathname;

  // 返回响应
  switch (uri) {
    case "/random":
      sseStart(res);
      sseRandom(res);
      break;
  }

}).listen(port);

console.log(`server running: http://localhost:${port}\n\n`);</code>

Utilisation de l'identifiant de données

Le serveur peut également choisir d'envoyer après la ligne data: id::

<code class="language-javascript">// SSE 头
function sseStart(res) {
  res.writeHead(200, {
    Content-Type: "text/event-stream",
    Cache-Control: "no-cache",
    Connection: "keep-alive"
  });
}</code>

Si la connexion est déconnectée, le navigateur renvoie le dernier ID au serveur dans l'en-tête HTTP du dernier événement-ID afin que le serveur puisse renvoyer les messages manqués.

Le dernier ID est également disponible dans la propriété .Lasteventid de l'objet de l'événement du client:

<code class="language-javascript">// SSE 随机数
function sseRandom(res) {
  res.write("data: " + (Math.floor(Math.random() * 1000) + 1) + "\n\n");
  setTimeout(() => sseRandom(res), Math.random() * 3000);
}</code>

Spécifiez Retry Delay

Bien que la reconnexion soit automatique, votre serveur peut savoir que de nouvelles données ne sont pas nécessaires pour une période spécifique, il n'est donc pas nécessaire de conserver un canal de communication actif. Le serveur peut envoyer une réponse retry: sur lui-même ou dans le cadre du message final, contenant la valeur millisenconde. Par exemple:

<code class="language-bash">$> curl -H Accept:text/event-stream http://localhost:8000/random
data: 481

data: 127

data: 975</code>

Après l'avoir reçu, le navigateur abandonnera la connexion SSE et tentera de se reconnecter une fois le délai de retard.

d'autres gestionnaires d'événements

En plus des événements "Message" et nommés, vous pouvez également créer des gestionnaires "Open" et "Error" dans Client JavaScript.

Lorsque la connexion du serveur est établie, l'événement "ouvert" sera déclenché. Il peut être utilisé pour exécuter un autre code de configuration ou initialiser les éléments DOM:

<code class="language-javascript">// 客户端 JS
const source = new EventSource("/random");</code>

Lorsque la connexion du serveur échoue ou se termine, l'événement "Erreur" est déclenché. Vous pouvez vérifier la propriété .Eventphase de l'objet de l'événement pour voir ce qui se passe:

<code class="language-javascript">source.addEventListener('message', e => {
  console.log('RECEIVED', e.data);
});</code>

N'oubliez pas, il n'est pas nécessaire de se reconnecter: Cela se produira automatiquement.

terminer la communication SSE

Le navigateur peut terminer la communication SSE à l'aide de la méthode .close () de l'objet Eventsource. Par exemple:

<code>event: news
data: SSE is great!

event: weather
data: { "temperature": "20C", "wind": "10Kph", "rain": "25%" }

event: stock
data: { "symbol": "AC", "company": "Acme Corp", "price": 123.45, "increase": -1.1 }</code>
Le serveur peut résilier la connexion par:

  1. déclencher res.end () ou envoyer retry: retard, alors
  2. Renvoie le statut HTTP 204 lorsque le même navigateur essaie de se reconnecter.

Seuls les navigateurs peuvent rétablir les connexions en créant un nouvel objet Eventsource.

Conclusion

Les événements côté serveur offrent un moyen d'implémenter les mises à jour de page en temps réel, ce qui peut être plus facile, plus pratique et plus léger que le sondage AJAX basé sur Fetch (). La complexité se situe du côté du serveur. Vous devez:

  1. Gardez toutes les connexions actives de tous les utilisateurs en mémoire, et
  2. Déclencher le transfert de données lorsque des modifications se produisent.

mais cela est complètement sous votre contrôle, et l'extension ne doit pas être plus complexe que toute autre application Web.

Le seul inconvénient est que SSE ne vous permet pas d'envoyer des messages du navigateur au serveur (à l'exception de la demande de connexion initiale). Vous pouvez utiliser Ajax, mais c'est trop lent pour les applications comme les jeux d'action. Pour une communication bidirectionnelle appropriée, vous avez besoin de WebSockets. Veuillez voir comment créer une application en direct à l'aide de WebSockets dans Node.js pour en savoir plus!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn