简体   繁体   English

在 Node.js 中实现服务器发送事件的简单方法?

[英]Simple Way to Implement Server Sent Events in Node.js?

I've looked around and it seems as if all the ways to implement SSEs in Node.js are through more complex code, but it seems like there should be an easier way to send and receive SSEs.我环顾四周,似乎所有在 Node.js 中实现 SSE 的方法都是通过更复杂的代码,但似乎应该有一种更简单的方法来发送和接收 SSE。 Are there any APIs or modules that make this simpler?是否有任何 API 或模块可以使这更简单?

Here is an express server that sends one Server-Sent Event (SSE) per second, counting down from 10 to 0:这是一个快速服务器,每秒发送一个服务器发送事件 (SSE),从 10 倒计时到 0:

const express = require('express')

const app = express()
app.use(express.static('public'))

app.get('/countdown', function(req, res) {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  })
  countdown(res, 10)
})

function countdown(res, count) {
  res.write("data: " + count + "\n\n")
  if (count)
    setTimeout(() => countdown(res, count-1), 1000)
  else
    res.end()
}

app.listen(3000, () => console.log('SSE app listening on port 3000!'))

Put the above code into a file (index.js) and run it: node index将上面的代码放入一个文件(index.js)中并运行: node index

Next, put the following HTML into a file (public/index.html):接下来,将以下 HTML 放入文件 (public/index.html):

<html>
<head>
  <script>
  if (!!window.EventSource) {
    var source = new EventSource('/countdown')

    source.addEventListener('message', function(e) {
      document.getElementById('data').innerHTML = e.data
    }, false)

    source.addEventListener('open', function(e) {
      document.getElementById('state').innerHTML = "Connected"
    }, false)

    source.addEventListener('error', function(e) {
      const id_state = document.getElementById('state')
      if (e.eventPhase == EventSource.CLOSED)
        source.close()
      if (e.target.readyState == EventSource.CLOSED) {
        id_state.innerHTML = "Disconnected"
      }
      else if (e.target.readyState == EventSource.CONNECTING) {
        id_state.innerHTML = "Connecting..."
      }
    }, false)
  } else {
    console.log("Your browser doesn't support SSE")
  }
  </script>
</head>
<body>
  <h1>SSE: <span id="state"></span></h1>
  <h3>Data: <span id="data"></span></h3>
</body>
</html>

In your browser, open localhost:3000 and watch the SSE countdown.在您的浏览器中,打开localhost:3000并观看 SSE 倒计时。

I'm adding a simple implementation of SSE here.我在这里添加了一个简单的 SSE 实现。 It's just one Node.js file.它只是一个 Node.js 文件。

You can have a look at the result here: https://glossy-ox.glitch.me/您可以在此处查看结果: https : //glossy-ox.glitch.me/

const http = require('http');
const port = process.env.PORT || 3000;

const server = http.createServer((req, res) => {
  // Server-sent events endpoint
  if (req.url === '/events') {
    res.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive',
    });

    const refreshRate = 1000; // in milliseconds
    return setInterval(() => {
      const id = Date.now();
      const data = `Hello World ${id}`;
      const message =
        `retry: ${refreshRate}\nid:${id}\ndata: ${data}\n\n`;
      res.write(message);
    }, refreshRate);
  }

  // Client side
  res.writeHead(200, {'Content-Type': 'text/html'});
  res.end(`
    <!DOCTYPE html>
    <html lang="en" dir="ltr">
      <head>
        <meta charset="utf-8">
        <title>SSE</title>
      </head>
      <body>
        <pre id="log"></pre>
      </body>
      <script>
        var eventSource = new EventSource('/events');
        eventSource.onmessage = function(event) {
          document.getElementById('log').innerHTML += event.data + '<br>';
        };
      </script>
    </html>
  `);
});

server.listen(port);

server.on('error', (err) => {
  console.log(err);
  process.exit(1);
});

server.on('listening', () => {
  console.log(`Listening on port ${port}`);
});

If you're using express this is the easiest way https://www.npmjs.com/package/express-sse如果您使用 express 这是最简单的方法https://www.npmjs.com/package/express-sse

on BE:在 BE:

const SSE = require('express-sse');

const sse = new SSE();

...

app.get('/sse', sse.init);

...

sse.send('message', 'event-name');

on FE:在 FE:

const EventSource = require('eventsource');

const es = new EventSource('http://localhost:3000/sse');

es.addEventListener('event-name', function (message) {
  console.log('message:', message)
});

I found SSE implementation in node.js.我在 node.js 中找到了 SSE 实现。

Github link: https://github.com/einaros/sse.js Github 链接: https : //github.com/einaros/sse.js

NPM module: https://www.npmjs.com/package/sse NPM 模块: https : //www.npmjs.com/package/sse

Will above link helps you ?上面的链接对你有帮助吗?

**client.js**

var eventSource = new EventSource("/route/events");
eventSource.addEventListner("ping", function(e){log(e.data)});

//if no events specified
eventSource.addEventListner("message", function(e){log(e.data)});

**server.js**

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

    if(req.url.indexOf("/route/events")>=){

      res.setHeader('Connection', 'keep-alive');

      res.setHeader("Cache-Control", "no-cache");

      res.setHeader("Content-Type", "text/event-stream");

      let event = "event: ping";

      let id = `id: ${Date.now()}`;

      let data = {
         message:`hello @${new Date().toString()}`
      }

      data = "data: "+JSON.stringify(data);

      res.end(`${event}\n${id}\n${data}\n\n`);
   }
}).listen(PORT)

You should be able to do such a thing using Socket.io .你应该能够使用Socket.io做这样的事情。 First, you will need to install it with npm install socket.io .首先,您需要使用npm install socket.io安装它。 From there, in your code you will want to have var io = require(socket.io);从那里,在您的代码中,您将需要var io = require(socket.io);

You can see more in-depth examples given by Socket.IO你可以看到Socket.IO 给出的更深入的例子

You could use something like this on the server:你可以在服务器上使用这样的东西:

var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('../..')(server);
var port = process.env.PORT || 3000;

server.listen(port, function () {
  console.log('Server listening at port ' + port);
});

app.use(express.static(__dirname + '/public'));

io.on('connection', function (socket) {
    socket.emit('EVENT_NAME', {data});
});

And something like this on the client:在客户端是这样的:

<script src="socket_src_file_path_here"></script>
<script>
  var socket = io('http://localhost');
  socket.on('EVENT_NAME', function (data) {
    console.log(data);
    //Do whatever you want with the data on the client
  });
</script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM