ホームページ >ウェブフロントエンド >jsチュートリアル >node.jsでサーバーセントイベントを使用する方法

node.jsでサーバーセントイベントを使用する方法

Joseph Gordon-Levitt
Joseph Gordon-Levittオリジナル
2025-02-08 09:31:09246ブラウズ

How to Use Server-sent Events in Node.js

コアポイント

  • サーバー送信イベント(SSE)を使用すると、サーバーはいつでもブラウザにデータをプッシュでき、リアルタイムニュースレポート、天気予報、株価などの機能を有効にします。ブラウザは、接続を確立するための最初の要求を発行し、サーバーは接続を開いたままにしてテキストメッセージを送信します。
  • サーバーは、任意の数のSSEチャネルURLまたは単一のエンドポイントURLを提供できます。サーバーからのメッセージには、特定のタイプの情報を識別するための関連するイベントがある場合があります。また、接続が切断されたときに見逃されたメッセージを再送信するために、データラインの後にIDを送信することもできます。
  • ブラウザは、eventsourceオブジェクトの.close()メソッドを使用してSSE通信を終了できます。サーバーは、res.End()をトリガーするか、再試行の遅​​延を送信することにより接続を終了し、同じブラウザが再接続しようとしたときにHTTPステータス204を返すことができます。新しいEventSourceオブジェクトを作成することにより、ブラウザのみが接続を再確立できます。
  • この記事では、Server Send Events(SSE)を使用して、クライアントがHTTP接続を介してサーバーから自動更新を受信できるようにする方法について説明します。また、その使用を調査し、node.jsを使用してサーバーを使用してイベントを送信する方法の実用的なデモを示します。

サーバーの送信イベントの利点

  • サーバー送信イベントのクイックスタート
  • 重要なヒント
    高度なサーバー送信イベント
  • シングルおよび複数のSSEチャネル
    • 単一のチャネルで異なるデータを送信します
    • データ識別子を使用して
    • retry遅延を指定
    • その他のイベントハンドラー
    • SSE通信を終了します
    結論
イベントを送信するサーバーの利点

Webは、リクエスト応答に基づいてHTTPメッセージに応答します。ブラウザはURL要求を発行し、サーバーはデータを返します。これにより、ブラウザは画像、CSS、JavaScriptなどをより多くのリクエストを行い、サーバーが応答する場合があります。サーバーはブラウザに積極的にメッセージを送信できないので、データが変更されたことをどのように示していますか?幸いなことに、サーバー送信イベント(SSE)を使用して、ライブニュースリリース、天気予報、株価などの機能を追加できます。

標準のWebテクノロジーを使用してリアルタイムのデータの更新を実現することは常に可能でした:

1990年代のWebは、フルページまたはフレーム/iframeを使用して更新されました。
  • 2000年代のWebはAjaxを導入しました。これは、長いポーリングを使用してデータを要求し、新しい情報で対応するDOM要素を更新できます。
  • ブラウザが更新をトリガーする必要があるため、これらのオプションはどちらも理想的ではありません。リクエストがあまりにも頻繁に行われた場合、データの変更はありません。そのため、ブラウザとサーバーの両方が不必要な作業を行います。ゆっくりとリクエストすると、重要な更新を見逃す可能性があり、あなたがフォローしている株価は急落しました!

サーバー送信イベント(SSE)により、サーバーはいつでもブラウザにデータをプッシュできます。

    ブラウザは、接続を確立するための最初の要求を引き続き行います。
  • サーバーはイベントストリーム応答を返し、接続を開いたままにします。
  • サーバーは、この接続を使用していつでもテキストメッセージを送信できます。
  • 着信データは、ブラウザでJavaScriptイベントを提起します。イベントハンドラー機能はデータを解析し、DOMを更新します。
本質的に、SSEは無制限のデータストリームです。インターセプトして読み取ることができる小片でダウンロードされた無限に大きなファイルをダウンロードすると考えてください。

SSEはもともと2006年に実装され、すべての主要なブラウザでこの標準をサポートしています。 WebSocketsとしてはあまり知られていないかもしれませんが、サーバーはイベントを簡単に送信し、標準のHTTPを使用し、一元配置通信をサポートし、自動再接続を提供します。このチュートリアルは、サードパーティモジュールのないNode.jsコードの例を提供しますが、SSEはPHPを含む他のサーバー側の言語で使用できます。

サーバーの送信イベントのクイックスタート

次のデモでは、少なくとも3秒ごとにランダムな間隔でランダムな間隔でランダム数を出力するnode.js Webサーバーを実装しています。

ここでnode.js SSEデモを見つけることができます。

このコードは、標準node.js HTTPおよびURLモジュールを使用してWebサーバーを作成し、URLを解析します。

サーバーは、 /ランダムパスに遭遇したときに着信URL要求をチェックし、反応します:
<code class="language-javascript">import http from "node:http";
import url from "node:url";</code>

それは最初にSSE HTTPイベントストリームヘッダーで応答します:

<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>

別の関数は乱数を送信し、ランダムな間隔が通過した後にそれ自体を呼び出します:

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

コードをローカルに実行する場合、端末でCurlを使用して応答をテストできます。

<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>
ctrl

|を押します。

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

data: 127

data: 975</code>
ブラウザのクライアントJavaScriptは、EventSourceオブジェクトコンストラクターを使用して /ランダムURIに接続します:

入力データは、メッセージイベントハンドラーをトリガーします。ここで、データ:文字列はイベントオブジェクトの.dataプロパティで使用可能です: 重要なヒント

fetch()と同様に、ブラウザは標準のHTTPリクエストを発行するため、CSP、CORSを処理し、2番目の

パラメーターをEventSourceコンストラクターに渡してCookieを送信する必要がある場合があります。
<code class="language-javascript">// 客户端 JS
const source = new EventSource("/random");</code>

サーバーは、接続された各ユーザーがデータを送信するために個別のRES応答オブジェクトを保持する必要があります。これは、次の呼び出しのために値を閉鎖に渡すことにより、上記のコードで達成されます。

<code class="language-javascript">source.addEventListener('message', e => {
  console.log('RECEIVED', e.data);
});</code>
メッセージデータは、形式データの文字列のみになります:

nn(おそらくJSON)。キャリッジリターンを終了することが重要です。

  • サーバーは、res.End()を使用していつでもSSE応答を終了できますが、...{ withCredentials: true }
  • 接続が中断されると、ブラウザは自動的に再接続しようとします。
  • Advanced Serverはイベントを送信します
  • SSEは上記よりも多くのコードを必要としませんが、次のセクションでは他のオプションについて説明します。

    シングルおよび複数のSSEチャネル

    サーバーは、任意の数のSSEチャネルURLを提供できます。たとえば、

    • /最新/ニュース
    • /最新/天気
    • /最新/stockprice

    これは、単一ページにトピックが表示されている場合は実用的かもしれませんが、単一のページにニュース、天候、株価が表示されている場合はそうではありません。この場合、サーバーは各ユーザーの3つの接続を維持する必要があります。これにより、トラフィックが増加するとメモリの問題が発生する可能性があります。

    別のオプションは、1つの通信チャネルにデータ型を送信する /最新 /最新などの単一のエンドポイントURLを提供することです。ブラウザは、 /最新の?type = news、weather、stockpriceなどのURLクエリ文字列に関心のあるトピックを示すことができます。これにより、サーバーは特定のメッセージに対するSSE応答を制限できます。

    単一のチャネルで異なるデータを送信します

    サーバーからのメッセージには、特定のタイプの情報を識別するために

    行の上に渡される関連event:を持つことができます。 data:

    これらは、クライアントの「メッセージ」イベントハンドラーをトリガーしません。イベントの種類ごとにハンドラーを追加する必要があります。たとえば、
<code class="language-javascript">import http from "node:http";
import url from "node:url";</code>

データ識別子を使用して

<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>

サーバーは、

data:の後に送信することもできます。 id:

接続が切断されている場合、ブラウザは最後のIDを最後のイベントID 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>

最新のIDは、クライアントのイベントオブジェクトの.lasteventidプロパティでも利用できます。

retry遅延を指定

<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>
再接続は自動ですが、サーバーは特定の期間に新しいデータが必要ないことを知っている可能性があるため、アクティブな通信チャネルを保持する必要はありません。サーバーは、ミリ秒の値を含む最終メッセージの一部として、それ自体に

応答を送信できます。たとえば、

retry:それを受信した後、ブラウザはSSE接続を放棄し、遅延時間が経過した後に再接続しようとします。

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

data: 127

data: 975</code>
その他のイベントハンドラー

「メッセージ」と名前付きイベントに加えて、クライアントJavaScriptに「オープン」ハンドラーと「エラー」ハンドラーを作成することもできます。

サーバー接続が確立されると、「オープン」イベントがトリガーされます。他の構成コードを実行したり、DOM要素を初期化するために使用できます。

サーバー接続が失敗または終了すると、「エラー」イベントがトリガーされます。イベントオブジェクトの.EventPhaseプロパティを確認して、何が起こっているのかを確認できます。

覚えておいてください、再接続する必要はありません:
<code class="language-javascript">// 客户端 JS
const source = new EventSource("/random");</code>
それは自動的に発生します。

SSE通信を終了します
<code class="language-javascript">source.addEventListener('message', e => {
  console.log('RECEIVED', e.data);
});</code>

ブラウザは、eventsourceオブジェクトの.close()メソッドを使用してSSE通信を終了できます。たとえば、

サーバーは、次のように接続を終了できます
  1. トリガーres.End()またはretry:遅延を送信してから
  2. を送信します
  3. 同じブラウザが再接続しようとしたときにHTTPステータス204を返します。

のみのブラウザのみが、新しいEventSourceオブジェクトを作成することで接続を再確立できます。

結論

サーバー側のイベントは、リアルタイムページの更新を実装する方法を提供します。これは、Fetch()ベースのAJAXポーリングよりも簡単で実用的で軽量です。複雑さはサーバー側にあります。あなたがする必要があります:

  1. すべてのユーザーのアクティブな接続をメモリに保ち、
  2. 変更が発生したときにデータ転送をトリガーします。
しかし、これは完全にあなたの管理下にあり、拡張機能は他のどのWebアプリケーションよりも複雑であってはなりません。

唯一の欠点は、SSEでブラウザからメッセージをサーバーに送信できないことです(初期接続要求を除く)。 Ajaxを使用できますが、これはアクションゲームなどのアプリケーションには遅すぎます。適切な双方向通信には、WebSocketが必要です。詳細については、node.jsでWebSocketsを使用してライブアプリケーションを作成する方法をご覧ください!

以上がnode.jsでサーバーセントイベントを使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。