长轮询 MySQL 数据库仅在更新时

Long Polling MySQL Database ONLY on UPDATE

好吧,也许我在这里遗漏了什么,但对于我来说,我不能完全理解这一点。我将 运行 这个 Ajax 本地主机上的长轮询脚本,所以我不担心请求的数量,但我仍然想让它工作。

我是 运行 分数管理员和显示记分牌。

在一个页面上,我有一个管理员,当你按下一个按钮时,它会向我的 table "roster" 的 "score" 列添加 10 点,其中 class 等于按钮的 class。我没有遇到任何问题正在更新数据库,我们只是在设置全貌。

在第二页。我有一个 ajax 调用,目前每秒触发一次并获取最近更新的行,并显示一个弹出窗口,通知用户某某的分数刚刚增加了 10 分。

两个问题:

  1. 它每秒都在发射。
  2. 即使数据库没有更新,它仍然在发射。

我知道我可以使用 ajax 长轮询来做到这一点,但我只是想不出如何将所有部分正确连接在一起,以便 ajax 调用仅在以下情况下触发我们更新了数据库。

JS

$(document).ready( function() {  
      pingScores();
    });

    var timestamp = null;

    function pingScores() {               
        $.ajax({ 
            type: "GET",
            url: "getUpdate.php?timestamp="+timestamp,
            cache: false,
            async: true,            
            success: function(data){
                var json = eval('(' + data + ')');  
                var notinyClass = json[2];
                var notinyName = json[3];
                //$.notiny({ text: notinyName+"<span class='addScore'> +10</span>", width: '100%', image: notinyClass }); - this is the popup API call that I am passing the class and the name to

                timestamp = json["timestamp"];  
                setTimeout("pingScores()", 1000);
            }
        });
    };

PHP (getUpdate.php)

<?php

 require "config.php"; //-- storing all login credentials elsewhere

 $db = mysql_connect($db_host, $db_user, $db_pass) or die(mysql_error());
 mysql_select_db($db_name) or die(mysql_error());

 $query = "SELECT * FROM roster ORDER BY last_updated DESC LIMIT 1";
 $result = mysql_query($query);
 $array = mysql_fetch_row( $result );

 echo json_encode($array);

 mysql_close();
?>

数据库

|id     | last_updated       | class | name  | score | active |
|-------|--------------------|-------|-------|-------|--------|
| 1     |2017-04-26 09:37:11 | alpha | Alpha | 10    | 1      |
|-------|--------------------|-------|-------|-------|--------|
| 2     |2017-04-26 09:32:59 | beta  | Beta  | 10    | 1      |
|-------|--------------------|-------|-------|-------|--------|
| 3     |2017-04-26 09:32:59 | delta | Delta | 10    | 1      |

当数据库从 ADD 指向分数的一系列按钮更新时,PHP 看起来像这样:

<?php
    require "config.php";

    $conn = new mysqli($db_host, $db_user, $db_pass, $db_name);
    if ($conn->connect_error) {
        die("Connection failed: " . $conn->connect_error);
    } 

    $class = $_POST["class"];

    $sql = "UPDATE roster SET score = score + '10', last_updated = now() WHERE class = '".$class."'";

    if ($conn->query($sql) === TRUE) {
        echo "Updated data successfully\n";
    } else {
        echo $conn->error;
    }

    $conn->close();
?>

我能找到的关于如何进行长轮询的每个教程都是从 txt 文件中提取数据,而关于如何从数据库中提取数据的说明并不是最清楚的。我希望得到关于如何执行此操作的一些说明。

如果我理解正确的话,您只想在发生更新时显示通知。您需要存储最后显示的通知,例如:

var timestamp = null,
    lastNotificationIdentifier = '';

function pingScores() {               
    $.ajax({ 
        type: "GET",
        url: "getUpdate.php?timestamp="+timestamp,
        cache: false,
        async: true,            
        success: function(data){
            var json = eval('(' + data + ')');  
            var notinyClass = json[2];
            var notinyName = json[3];
            var localIdentifier = json.last_updated + json.id

            //check if we've displayed this record/timestamp before
            if (localIdentifier !== lastNotificationIdentifier) {

                //if not then go ahead and show the notification
                //$.notiny({ text: notinyName+"<span class='addScore'> +10</span>", width: '100%', image: notinyClass }); - this is the popup API call that I am passing the class and the name to

                //making sure to save some unique information about having shown this notification
                lastNotificationIdentifier = localIdentifier;
            }

            timestamp = json["timestamp"];  
            setTimeout("pingScores()", 1000);
        }
    });
};

您可以只使用 last_updated 列作为您的唯一标识符,以确保不会多次显示通知,但这在技术上不是唯一的,因为您可以在同一秒内更新两个列.这就是为什么我混合使用时间戳和记录 ID。

就此 AJAX 运行 每秒一次而言,这就是您将超时设置为的时间:

setTimeout("pingScores()", 1000);

超时延迟以毫秒为单位设置,如果您想要 5 秒,您可以使用 5000。您可能会看到快速加载时间,因为这是 运行 本地,因此每个请求加载所花费的时间可能可以忽略不计。