sse简介
Server-Sent Events(SSE)是一种用于实现服务器向客户端实时推送数据的Web技术。与传统的轮询和长轮询相比,SSE提供了更高效和实时的数据推送机制。
SSE基于HTTP协议,允许服务器将数据以事件流(Event Stream)的形式发送给客户端。客户端通过建立持久的HTTP连接,并监听事件流,可以实时接收服务器推送的数据。
SSE的主要特点包括:
1. 简单易用:SSE使用基于文本的数据格式,如纯文本、JSON等,使得数据的发送和解析都相对简单。
2. 单向通信:SSE支持服务器向客户端的单向通信,服务器可以主动推送数据给客户端,而客户端只能接收数据。
3. 实时性:SSE建立长时间的连接,使得服务器可以实时地将数据推送给客户端,而无需客户端频繁地发起请求。
代码块
laravel后端
/**
* 消息推送-sse-实时推送
*/
public function realTimeMessagePush(Request $request){
$userId = $request->get("userId")??0; # 因多个用户,向指定用户推送
ob_end_clean(); #函数清除,该函数清除php缓冲区内的内容,并且关闭输出缓冲区
$response = response()->stream(function () use ($userId){
while (true) {
#推送缓存
# 将数据存储到redis-list中,缓存10秒,实现当用户在线时推送,不在线不推送
$messageRedis = Redis::lpop("mailMessage:".$userId);
if ($messageRedis){
$messageRedis = json_decode($messageRedis,true);
if (isset($userId) && $userId == $messageRedis['to_id']){
#echo "retry: 2000\n";#失败重连(毫秒)
echo 'data: '.json_encode($messageRedis)."\n";
echo "\n";
}
}
if(ob_get_level()>0){
ob_flush();
}
flush();
if (connection_aborted()) {break;}
sleep(2); # 2秒推送一次
}
}, 200, [
'Cache-Control' => 'no-cache',
'X-Accel-Buffering' => 'no',
'Content-Type' => 'text/event-stream',
]);
return $response;
}
前端代码
弹出页面消息,3秒后消失
<!DOCTYPE html>
<html>
<head>
<title>SSE Example</title>
<style>
.notification-container {
position: fixed;
top: 10px;
right: 10px;
max-width: 300px;
width: 100%;
}
.notification {
padding: 10px;
background-color: #f0f0f0;
border: 1px solid #ccc;
border-radius: 5px;
opacity: 0;
transform: translateX(100%);
transition: transform 0.5s, opacity 0.5s;
animation: slide-in 0.5s forwards;
}
.show {
opacity: 1;
transform: translateX(0);
}
</style>
</head>
<body>
<input type="text" id="userId" value="{{$userId}}">
<div id="sse-output"></div>
<div class="notification-container" id="notification-container">
</div>
<script>
//页面动画
var notificationContainer = document.getElementById('notification-container');
function showNotification(message) {
var notification = document.createElement("div");
notification.classList.add("notification", "show");
notification.textContent = message;
notificationContainer.appendChild(notification);
setTimeout(function() {
notification.style.transition = "transform 0.5s, opacity 0.5s";
notification.style.transform = "translateX(100%)";
notification.style.opacity = "0";
setTimeout(function() {
notification.remove();
}, 500);
}, 3000); // 3秒后自动关闭
}
//sse使用
const userId = document.getElementById('userId').value;
//EventSource 不允许传header头部,并且只能用get请求
const eventSource = new EventSource('/realTimeMessagePush?userId='+userId);
//eventSource.onopen = function(data){
// console.log("连接成功")
//}
eventSource.onmessage = function(event) {
const data = JSON.parse(event.data);
console.log('Received message:', data);
// 在此处执行你的前端操作,比如更新页面元素
showNotification(data.title)
};
//eventSource.onerror = function(event) {
// console.error('Error occurred:', event);
// eventSource.close();
//};
</script>
</body>
</html>
效果展示
laravel+sse