Длинный опрос базы данных MySQL ТОЛЬКО при ОБНОВЛЕНИИ

хорошо, может быть, я что-то здесь упускаю, но, хоть убей, я не могу этого понять. Я собираюсь запустить этот сценарий длительного опроса Ajax на локальном хосте, поэтому меня не беспокоит количество запросов, но я все же хотел бы, чтобы он работал.

Я запускаю администратора очков и отображаю табло.

На одной странице у меня есть администратор, который, когда вы нажимаете кнопку, добавляет 10 баллов в столбец «оценка» моей таблицы «список», где класс равен классу кнопки. У меня нет НИКАКИХ проблем Обновление базы данных, мы просто настраиваем всю картину.

На второй странице. У меня есть вызов ajax, который в настоящее время срабатывает каждую секунду и получает самую последнюю обновленную строку, а также отображает всплывающее окно, уведомляющее пользователя о том, что 10 баллов были только что добавлены к счету So-And-So.

Две проблемы:

  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-файла, а инструкции о том, как извлекать данные из базы данных, не самые четкие. Я надеюсь получить некоторые разъяснения о том, как это сделать.


person Murphy1976    schedule 26.04.2017    source источник
comment
Вы видели, что это конкретное решение извлекает данные из текстового файла, верно?   -  person Murphy1976    schedule 26.04.2017
comment
Вы смешиваете драйверы mysql и mysqli. Драйверы mysql устарели с версии 5.5 (июнь 2013 г.) и удалены с версии 7.0 (декабрь 2015 г.). Вы также уязвимы для атак путем внедрения кода SQL. Вы должны использовать mysqli или PDO подготовленные операторы со связанными параметрами как описано в этом сообщении.   -  person Alex Howansky    schedule 26.04.2017
comment
Я запускаю это исключительно на локальном хосте - как было сказано ранее, но спасибо за советы по лучшей практике.   -  person Murphy1976    schedule 26.04.2017


Ответы (1)


Если я правильно понимаю, вы хотите отображать уведомление только в том случае, если произошло обновление. Вам нужно будет сохранить последнее отображаемое уведомление, например:

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 в качестве своего уникального идентификатора, чтобы убедиться, что уведомление не отображается более одного раза, но это технически не уникально, поскольку у вас может быть два столбца, которые были обновлены в одну и ту же секунду. Вот почему я использовал смесь временной метки и идентификатора записи.

Поскольку этот AJAX запускается раз в секунду, вы установили время ожидания:

setTimeout("pingScores()", 1000);

Задержки тайм-аута устанавливаются в миллисекундах, если вы хотите 5 секунд, вы должны использовать 5000. Вероятно, вы видите быстрое время загрузки, так как это выполняется локально, поэтому время, необходимое для загрузки каждого запроса, вероятно, незначительно.

person Jasper    schedule 26.04.2017
comment
Я знаю, почему он работает каждую секунду, это единственный известный мне способ. Я должен был объяснить это в исходном посте. Я дам этому водоворот и дам вам знать. Спасибо @jasper - person Murphy1976; 26.04.2017
comment
@Murphy1976 Murphy1976 Если вы хотите, чтобы код уведомления запускался только тогда, когда происходит обновление (а не через заранее определенный интервал), вы больше не проводите длительный опрос, у вас есть открытая связь сервера с клиентом. Есть разные способы добиться этого, но они намного сложнее. - person Jasper; 26.04.2017
comment
@ Murphy1976 Не за что. Если вас интересуют другие способы сделать это, ознакомьтесь с веб-сокетами или веб-API. Они намного сложнее, но довольно гладкие. - person Jasper; 26.04.2017