laravel+sse实现实时推送

sse简介

复制代码
Server-Sent Events(SSE)是一种用于实现服务器向客户端实时推送数据的Web技术。与传统的轮询和长轮询相比,SSE提供了更高效和实时的数据推送机制。

SSE基于HTTP协议,允许服务器将数据以事件流(Event Stream)的形式发送给客户端。客户端通过建立持久的HTTP连接,并监听事件流,可以实时接收服务器推送的数据。

SSE的主要特点包括:
 1. 简单易用:SSE使用基于文本的数据格式,如纯文本、JSON等,使得数据的发送和解析都相对简单。 
 2. 单向通信:SSE支持服务器向客户端的单向通信,服务器可以主动推送数据给客户端,而客户端只能接收数据。
 3. 实时性:SSE建立长时间的连接,使得服务器可以实时地将数据推送给客户端,而无需客户端频繁地发起请求。

代码块

laravel后端

php 复制代码
	/**
     * 消息推送-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秒后消失
html 复制代码
<!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

相关推荐
SDWAN_Cheap11 小时前
TCP滑动窗口与拥塞控制是什么?从流量控制到网络稳定性的完整解析
网络·tcp/ip·php
白露与泡影13 小时前
Redis 的“单线程”与“多线程”:一场关于性能与简洁的权衡
数据库·redis·php
CRMEB系统商城14 小时前
前后端技术栈全面换代!CRMEB 多商户(Java)v3.0更新预告
java·开发语言·小程序·php
码云数智-大飞15 小时前
新手写 Python 代码,如何规范命名、减少 Bug
开发语言·python·php
DevUp16 小时前
那些 CMS 的 AI 功能,到底有几个真能用
aigc·php·cms
迪康Defender16 小时前
终端安全实践:浅谈端点安全管理系统内置终端防火墙能力
运维·服务器·网络·经验分享·安全·php·终端安全管理
程序员_小兵17 小时前
PCIe Switch Fabric 技术解析
服务器·c语言·嵌入式硬件·php·fabric
新鲜势力呀17 小时前
PHP 实战:用户登录频繁失败怎么办?从安全防护到登录系统架构优化完整方案
安全·系统架构·php
我们从未走散19 小时前
AI 生图平台如何避免资损:用“扣款与凭据同事务”构建三态账本
开发语言·数据库·php
PHP实战开发录20 小时前
PHP接口大整数为什么变了
开发语言·php