本文主要记录SSE通讯的简介、使用、以及原理和一个ChatGPT返回数据的demo。
SSE(Server-Sent Events,服务器推送事件)是一种用于在浏览器和服务器之间实现实时、单向通信的Web技术。它允许服务器向客户端推送数据,而无需客户端发起请求。与传统的HTTP请求-响应模式不同,SSE建立了一种持久的连接,通过这个连接,服务器可以随时向客户端发送更新的数据。这种实时通信的方式非常适用于需要实时更新数据的应用,如聊天应用、股票行情、实时监控等。
EventSource
对象并监听事件即可实现实时通信。需要注意的是,SSE在一些旧版本的浏览器中可能不被完全支持。但是,大多数现代浏览器都支持SSE,并且可以通过Polyfill
来提供兼容性支持。
Polyfill是一种用于填充浏览器或环境中缺少的功能或API的代码。它可以在旧版本的浏览器或不支持某些新特性的环境中,提供对这些功能的兼容性支持。当新的Web标准或API被引入时,不同的浏览器或环境可能会以不同的速度进行支持和实现。在这种情况下,开发人员可以使用Polyfill来填充这些缺失的功能。
Polyfill通常是一个JavaScript库或脚本,它通过在运行时检测浏览器或环境的功能支持情况,然后根据需要动态地添加缺失的功能或API的实现。例如,如果某个浏览器不支持ES6的新特性,如箭头函数、模板字符串等,开发人员可以使用相应的Polyfill来提供对这些特性的支持。Polyfill会检测浏览器是否支持这些特性,如果不支持,则在运行时添加相应的代码来实现这些特性。
需要注意的是,Polyfill并不是一种通用的解决方案,它可能会增加页面的加载时间和代码体积。因此,在使用Polyfill时,需要根据具体的需求和目标浏览器进行选择和优化。
EventSource
对象来与服务器建立连接。message
事件,来接收服务器发送的数据。message
事件、open
事件、error
事件等。SSE基于HTTP协议,利用其长连接特性,通过浏览器向服务器发送一个HTTP请求,建立一条持久化连接。
WebSocket
)EventSource
是HTML5中的一个API,用于在客户端与服务器之间建立基于HTTP的单向通信。
EventSource
对象:new EventSource(url,options)
来创建一个EventSource
对象.
options
是配置项可选参数Object
类型,常用配置包括:
withCredentials
:Boolean
类型,标识是否允许发送Coolie
和HTTP
认证信息。默认false
headers
:Object
类型,标识发送的请求头信息。retryInterval
:Number
类型,标识与服务器失去连接后,重连时间间隔。默认1000毫秒 const sse = new EventSource('http://localhost:3000/api/sse',{
withCredentials:false,
headers:{},
retryInterval: 1000
})
onmessage
:表示已经收到服务端数据。onopen
:表示已经建立了连接,并开始接收服务端数据。当后端没有定义返回的事件,默认是该事件。onerror
:表示建立连接或接收数据时发生错误。EventSource
对象会触发相应的事件,客户端可以通过事件监听器来接收和处理这些事件。 sse.onopen = (e) =>{
console.log('连接成功', e)
}
sse.onmessage = (e) =>{
console.log('接收到数据', e)
}
sse.onerror= (e) =>{
console.log('发生错误',e)
}
sse.addEventListener('message',(e)=>{
const span = document.getElementById('animate')
span.remove()
message.innerHTML += `${e.data}|`
})
EventSource
对象的close()
方法来关闭连接。stop.addEventListener('click',(e)=>{
console.log('断开连接',e)
sse.close()
})
后端必须设置响应头 'Content-Type': 'text/event-stream'
,然后其他就和普通get请求一样。
后端是可以设置事件名称的,返回event 表示定义事件名称
res.write(`event:dg\n`)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<style>
.box{
height: 100vh;
width: 100%;
background: #1B1A22;
}
#message{
color: white;
}
#animate{
display: inline-block;
padding:0 5px;
font-size:20px;
font-weight: bold;
animation: fade 1s infinite forwards;
}
@keyframes fade {
from{
opacity: 0;
}
to {
opacity: 1;
}
}
</style>
<body>
<div>
<div class="box">
<div id="message"><span id="animate">|</span></div>
<div style="margin-top: 30px"><button id="stop">断开连接</button></div>
</div>
</div>
</body>
<script>
const message = document.getElementById('message')
const stop = document.getElementById('stop')
document.addEventListener('keydown',(e)=>{
if (e.keyCode == 13){
const sse = new EventSource('http://localhost:3000/api/sse',{
withCredentials:false,
headers:{},
retryInterval: 1000
})
sse.onopen = (e) =>{
console.log('连接成功', e)
}
sse.onmessage = (e) =>{
console.log('接收到数据', e)
}
sse.onerror= (e) =>{
console.log('发生错误',e)
}
sse.addEventListener('message',(e)=>{
const span = document.getElementById('animate')
span.remove()
message.innerHTML += `${e.data}|`
})
stop.addEventListener('click',(e)=>{
console.log('断开连接',e)
sse.close()
})
}
})
</script>
</html>
这里后端用Node
app.get('/api/sse',(req,res)=>{
res.writeHead(200,{
'Content-Type': 'text/event-stream',
'Access-Control-Allow-Origin': '*'
})
// 读取本地文件
const txt = fs.readFileSync('../SSE/index.txt','utf8')
// 分割成字符数组
const arr = txt.split('')
let currnet = 0
let timer = setInterval(()=>{
if (currnet < arr.length){
// 设置返回事件名称
// res.write(`event:dg\n`)
res.write(`data:${arr[currnet]}\n\n`)
currnet++
}else{
clearTimeout(timer)
}
},300)
})
注:
SSE是服务端主动向客户端发送数据,在客户端发送连接数据连接后,客户端就不能再向服务端发送数据了,只能服务端给客户端发送数据,这是因为SSE是单工通讯的。
只接受get请求
服务端没有设置正确的响应头信息,可能导致无法接收数据
总的来说,SSE是一种简单、实时的通信技术,适用于需要实时推送数据的应用场景,提供了一种有效的方式来实现服务器向客户端的实时通信。