即时响应之道:深入浅出Server-Sent Events

SSE简介

它是基于HTTP的持久长连接,服务器向客户端持续发送数据,客户端不难反向向服务器发送数据。它使得客户端能从服务器自动接收到更新使用SSE时候客户端与服务器建立了一个持久的长连接然后服务器利用这个连接向客户端持续发送数据。通过SSE客户端不能向服务器发送数据。客户端通过建立一个新的EventSource对象向服务器发出请求并打开一个持久连接,服务器接受到这个连接后保持打开状态当服务器端数据更新它就通过这个连接发送数据更新事件。因为连接始终保持打开状态所以服务器可以随时发送更多的事件。客户端监听这些事件既可获得数据更新。

SSE的优势和局限性

SSE技术是具有简单性,效率高,自动重连。局限性有限的浏览器支持,仅仅文本,单向通信。 一旦客户端通过HTTP连接订阅了特定的事件流,服务器就可以在任何时间点向客户端发送更新或消息。这与传统的请求-响应模型不同,在传统模型中,必须由客户端发起请求才能从服务器获取信息。 一旦SSE连接建立之后,客户端就无法再通过这个SSE连接直接发送额外的数据或指令给服务器了。也就是说,SSE不支持像WebSocket那样的全双工通信模式,后者允许客户端和服务器之间随时相互发送消息。 默认情况下,SSE 的连接是通过 HTTP GET 请求建立的,因此可以通过 URL 参数将数据传递给后端。 优势一:简单性,SSE在客户端的实现非常简单,大多数现代浏览器都原生支持EventSource接口,效率高由于连接是持久的服务器可以随时发生数据无需客户端频繁请求。减少了HTTP请求开销。三、自动重连。如果连接意外关闭EventSource接口会自动尝试重新连接。局限性一、有限的浏览器支持虽然大部分现代浏览器都支持SSE,但在一些旧版浏览器或某些移动浏览器中可能不被支持。二、仅文本:SSE只支持文本数据,不适用于二进制数据的传输。三、单向通信SSE只支持从服务器到客户端的单向数据流如果需要双向通信则可能考虑其它的技术如webSocket. 综上所述:SSE需要服务器向客户端不断推送数据,不需要客户端反向向服务器推送数据。 有如下场景可以考虑:新闻标题,比赛打分,股价和外汇交易等数据的实时更新。

SSE应用场景

近两年ChatGPT大火,在其背后正是使用了SSE技术如果我们让gpt生成一篇文章请求一旦提交服务器就会开始处理并逐步生成这篇文章,文章的生成通常是批量进行的而不是一次性完成的。在此过程中ChatGPT的服务器利用了SSE技术。将文章的各个部分依次推送到客户端,因此如果回复内容较多你可能会发现ChatGPT的响应呈现出逐步出现的形式。这正是利用了SSE技术。

demo演示

js 复制代码
<template>  
<div class="sse-demo">  
<h1>Server-Sent Events (SSE) Demo</h1>  
<div v-if="messages.length === 0" class="waiting">  
Waiting for messages from the server...  
</div>  
<ul v-else>  
<li v-for="(message, index) in messages" :key="index">  
{{ message }}  
</li>  
</ul>  
</div>  
</template>  
  
<script setup>  
import {onMounted, onUnmounted, ref} from 'vue';  
  
// 定义一个响应式数组,用于存储接收到的消息  
const messages = ref([]);  
  
// 定义 EventSource 对象  
let eventSource;  
  
onMounted(() => {  
// 创建 EventSource 实例,指定服务器端的 SSE 接口地址  
eventSource = new EventSource('/sse-endpoint'); // 替换为你的服务器端 SSE 接口  
  
// 监听服务器推送的消息  
eventSource.onmessage = (event) => {  
const newMessage = event.data; // 获取服务器推送的数据  
messages.value.push(newMessage); // 将消息添加到响应式数组中  
};  
  
// 监听错误事件  
eventSource.onerror = (error) => {  
console.error('EventSource failed:', error);  
eventSource.close(); // 关闭连接  
};  
});  
  
onUnmounted(() => {  
// 在组件卸载时关闭 EventSource 连接  
if (eventSource) {  
eventSource.close();  
}  
});  
</script>  
  
<style scoped>  
.sse-demo {  
font-family: Arial, sans-serif;  
margin: 20px;  
}  
  
.waiting {  
color: #888;  
font-style: italic;  
}  
  
ul {  
list-style-type: none;  
padding: 0;  
}  
  
li {  
background-color: #f9f9f9;  
border: 1px solid #ddd;  
margin-bottom: 5px;  
padding: 10px;  
border-radius: 4px;  
}  
</style>
js 复制代码
const express = require('express');  
const app = express();  
  
app.get('/sse-endpoint', (req, res) => {  
// 设置响应头,启用 SSE  
res.setHeader('Content-Type', 'text/event-stream');  
res.setHeader('Cache-Control', 'no-cache');  
res.setHeader('Connection', 'keep-alive');  
  
// 发送初始消息  
res.write(`data: Connected to SSE stream\n\n`);  
  
// 模拟每隔 5 秒发送一条消息  
const intervalId = setInterval(() => {  
const message = `Server time: ${new Date().toLocaleTimeString()}`;  
res.write(`data: ${message}\n\n`);  
}, 5000);  
  
// 当客户端断开连接时清理定时器  
req.on('close', () => {  
clearInterval(intervalId);  
res.end();  
});  
});  
  
// 启动服务器  
app.listen(3000, () => {  
console.log('Server is running on http://localhost:3000');  
});
相关推荐
UI前端开发工作室18 分钟前
数字孪生技术为UI前端提供新视角:产品性能的实时模拟与预测
大数据·前端
Sapphire~21 分钟前
重学前端004 --- html 表单
前端·html
遇到困难睡大觉哈哈1 小时前
CSS中的Element语法
前端·css
Real_man1 小时前
新物种与新法则:AI重塑开发与产品未来
前端·后端·面试
小彭努力中1 小时前
147.在 Vue3 中使用 OpenLayers 地图上 ECharts 模拟飞机循环飞行
前端·javascript·vue.js·ecmascript·echarts
老马聊技术1 小时前
日历插件-FullCalendar的详细使用
前端·javascript
咔咔一顿操作1 小时前
Cesium实战:交互式多边形绘制与编辑功能完全指南(最终修复版)
前端·javascript·3d·vue
LuckyLay2 小时前
使用 Docker 搭建 Rust Web 应用开发环境——AI教你学Docker
前端·docker·rust
pobu1683 小时前
aksk前端签名实现
java·前端·javascript
烛阴3 小时前
带参数的Python装饰器原来这么简单,5分钟彻底掌握!
前端·python