【发布时间】:2020-04-28 01:15:16
【问题描述】:
我正在尝试使用 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 来显示它。 我在其中一个方面都取得了成功,但不是同时在两个方面都取得了成功。
【问题讨论】:
-
我要指出的第一件事是,您不能将
clientRes保存在 Express 路由处理程序之外的范围内,因为这意味着每个路由都会覆盖前一个路由。所有模块范围的变量都由所有路由共享。相反,您需要从路由内部调用您的代码并将其传递给那里的res。这不是您要问的问题,但很快就会成为问题。
标签: javascript node.js server-sent-events