laravel+sse实现实时推送

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值