即时响应之道:深入浅出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');  
});
相关推荐
1024小神7 分钟前
在GitHub action中使用添加项目中配置文件的值为环境变量
前端·javascript
齐尹秦15 分钟前
CSS 列表样式学习笔记
前端
Mnxj20 分钟前
渐变边框设计
前端
用户76787977373222 分钟前
由Umi升级到Next方案
前端·next.js
快乐的小前端23 分钟前
TypeScript基础一
前端
北凉温华24 分钟前
UniApp项目中的多服务环境配置与跨域代理实现
前端
源柒25 分钟前
Vue3与Vite构建高性能记账应用 - LedgerX架构解析
前端
Danny_FD26 分钟前
常用 Git 命令详解
前端·github
stanny27 分钟前
MCP(上)——function call 是什么
前端·mcp
1024小神33 分钟前
GitHub action中的 jq 是什么? 常用方法有哪些
前端·javascript