如何筛选重复消息的SSE脚本

How to filter SSE script for duplicate messages?

本文关键字:消息 SSE 脚本 何筛选 筛选      更新时间:2024-01-11

我创建的服务器发送事件实现中似乎有一个奇怪的错误。问题似乎在于客户端通过过滤系统。问题是,脚本应该只在有新信息时更新应用程序数据流,而不是不断重复所有内容。目前,脚本会阻止流重复除最后一条消息之外的所有内容。最后一条消息是唯一一条无限期重复的消息。

我也试着在服务器端过滤消息,但似乎没有用。任何我遗漏的信息,只要问一下,我会非常乐意为您提供。

客户端Javascript

function getMsgs() {
    if (typeof(EventSource) !== "undefined") {
        var source = new EventSource('');
        var last_id;
        var used = {};
        source.addEventListener('message', function(event) {
            if (event.origin != 'http://example.com') {
                alert('Error: Unidentified origin!');
                return;
            } else {
                var now_id = event.lastEventId;
                if (window.matchMedia("screen and (max-width: 800px)").matches) {
                    if (last_id != now_id && document.getElementById('content').innerHTML != event.data) {
                        last_id = event.lastEventId;
                        if (!used[event.data]) {
                            document.getElementById('content').innerHTML += event.data;
                            used[event.data] = 1;
                        }
                    }
                } else {
                    if (last_id != now_id && document.getElementById('chatMsgs').innerHTML != event.data) {
                        last_id = event.lastEventId;
                        if (!used[event.data]) {
                            document.getElementById('chatMsgs').innerHTML += event.data;
                            used[event.data] = 1;
                            document.getElementById('chat').scrollTop = document.getElementById('chat').scrollHeight; //keep scrollbar at the bottom
                        }
                    }
                }
            }
        }, false);
    }

服务器端PHP

*用户登录时预先设置lstMsg会话

<?php
session_start();
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
include "../includes/config.php"; 
include "../includes/functions.php";
function getMessages($time) {
    $con = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);   
    $con->exec("SET CHARACTER SET utf8"); 
    $getLastMsg = "SELECT MAX(`sent`) FROM `messages` WHERE `msg_to` = '$_SESSION[username]' AND `type` = '0' LIMIT 1";
    $retrieveTime = $con->query($getLastMsg);
    $_SESSION['lstMsg'] = $retrieveTime->fetchColumn(PDO::FETCH_ASSOC);
    $getMsgs = "SELECT * FROM `messages` WHERE `msg_to` = '$_SESSION[username]' AND `type` = '0' AND `sent` > '$time' ORDER BY `sent` ASC";
    $receivedMsgs = $con->query($getMsgs); 
    foreach ($receivedMsgs->fetchAll() as $msg) { 
        $getUI = "SELECT `profile_pic`, `full_name`, `username` FROM `users` WHERE `username` = '$msg[msg_from]'";
        $uiQuery = $con->query($getUI);
        while ($UI = $uiQuery->fetch(PDO::FETCH_ASSOC)) { 
            echo "id: {$msg['id']}'n"; 
            echo "data: <article class='post'>'n"; 
            echo "data: <img src='{$UI[profile_pic]}' alt='{$UI[full_name]}' />'n"; 
            echo "data: <section class='pContainer'>'n";
            echo "data: <p class='timeAgo'>". Agotime($msg[sent]) ."</p>'n"; 
            echo "data: <a style='position:absolute;' href='/profile?uid={$UI[username]}'>{$UI['full_name']}</a><br />'n"; 
            echo "data: <h4>@{$msg['msg_from']}</h4>'n"; 
            echo "data: <p class='postContent'>{$msg['message']}</p>'n"; 
            echo "data: </section>'n"; 
            echo "data: </article>'n'n"; 
        } 
            ob_flush();
            flush();
            sleep(1);
    }
}
getMessages($_SESSION['lstMsg']);
?>

我也遇到了同样的问题,最终找到了阻止(来自服务器的)最后一条消息重复的方法。

$sql = "SELECT * FROM `table_name` WHERE `id` > '$_SESSION["id"]'";
$result = mysqli_query($conn, $sql);
while($row = mysqli_fetch_assoc($result)) {
            echo $row["data_from_database"];
            if($_SESSION["id"] < $row["id"]){
                $_SESSION["id"] = $row["id"];
        }
}

但是,您必须在页面上设置$_SESSION["id"]变量,该变量正在为SSE建立(调用)连接,否则它将无法工作。