使用服务器端事件(SSE)使用Javascript将更新推送到Web客户端

问题描述 投票:0回答:1

我正在尝试使用Javascript和Node.JS中的服务器端事件(SSE)将更新推送到Web客户端。为了简单起见,我有一个函数,它将每秒生成一次时间:

setTimeout(function time() {
  sendEvent('time', + new Date);
  setTimeout(time, uptimeTimeout);
}, 1000);

sendEvent函数以预期的格式组合事件,并将其发送到客户端。

var clientRes;
var lastMessageId = 0;
function sendEvent(event, message) {
  message = JSON.stringify(message);
  ++lastMessageId;
  sendSSE(clientRes, lastMessageId, event, message);
}

clientRes值来自服务器功能,用于处理来自基本URL的路由。

    app.use('/', function (req, res) {
        clientRes = res;
        ...
    }

我想在客户端UI上实现的是一个显示以下内容的简单页面:

>   <h1>The current time is {event.data}</h1>

我从服务器收到的最新消息数据中得出当前时间。

我创建了一个index.html文件,以使客户端侦听这些服务器发送的消息:

<!DOCTYPE html>
<html>
<body>

<h1>Getting server updates</h1>
<div id="result"></div>

<script>
if(typeof(EventSource) !== "undefined") {
  console.log("Event source is supported");
  var source = new EventSource("localhost:3000");
  source.onmessage = function(event) {
    document.getElementById("result").innerHTML += "=>" + event.data + "<br>";
  };
} else {
  console.log("Event source not supported");
  document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
evtSource.addEventListener("time", function(event) {
  const newElement = document.createElement("li");
  const time = JSON.parse(event.data).time;
  console.log("Time listener found time " + time);
  newElement.innerHTML = "ping at " + time;
  eventList.appendChild(newElement);
});
</script>
</body>
</html> 

如果我使用此index.html响应GET请求,则看不到任何时间消息。也就是说,此服务器代码不起作用:

app.use("/", function(request, response) {
    response.sendFile(__dirname + "/index.html");
    clientRes = response;
});

但是,如果我不对index.html文件做出响应,而是允许服务器将时间戳推送到客户端,它们将显示在浏览器中:

event: time
id: 104
data: 1587943717153

event: time
id: 105
data: 1587943727161
...

这里就是我被困住的地方。看来我已经成功地使服务器每秒推送新的时间戳。浏览器正在查看它们并显示文本。但是消息从服务器到达并不会触发侦听器,并且不会基于index.html呈现消息。

我见过的使用SSE的大多数示例都涉及PHP数据源。我需要服务器生成数据并提供HTML来显示它。我在一项或多项中都取得了成功,但不是同时取得了成功。

javascript node.js server-sent-events
1个回答
0
投票

我弄清楚了我所缺少的。我没有正确指定端点。对于根端点,服务器代码需要传递index.html文件。

app.use("/", function(request, response) {
    console.log("In root handler");
    response.sendFile(__dirname + "/index.html");
});

Index.html包含创建事件源的脚本:

    var source = new EventSource("http://localhost:3000/time");

但是作为EventSource构造函数的输入传入的URL必须是不同的终结点(不是root)。它必须是生成时间戳的端点。因此,在服务器中,/ time端点的处理程序是用于推送数据的处理程序。

app.use('/time', function (req, res) {
      res.writeHead(200, {
        'content-type': 'text/event-stream',
        'cache-control': 'no-cache',
        'connection': 'keep-alive'
      });

      // Save the response 
      clientRes = res;
});
© www.soinside.com 2019 - 2024. All rights reserved.