单击按钮后为所有连接的用户重新加载页面

Reload page for all connected user after one's clicking a button

@LSerni 我也使用数据库编辑了代码,但我仍然被阻止:(

它执行 clicked.php 但检查状态似乎不起作用。

我在 table 中有 2 个字段,如果第二个字段高于第一个,则页面必须重新加载,但目前情况并非如此,clicked.php 文件有效美好的。检查-status.php:

<?php
$reply = [ 'status' => 'success', 'pressed' => false ];

for ($sec = 0; $sec < 60; $sec++) {
     // ... check whether anyone pressed the button ...
   $mysqli = new mysqli("localhost", "risicov19", "Edukapol19", "my_risicov19");
    if ($mysqli->connect_errno) {
    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
    }
    $sql = "SELECT pre FROM data";
    $rs = mysqli_query($mysqli, $sql);
    while($row = mysqli_fetch_assoc($rs)) {
    $val1 = $row['pre'];
     }
    $sql = "SELECT data FROM data";
    $rs = mysqli_query($mysqli, $sql);
    while($row = mysqli_fetch_assoc($rs)) {
    $val2 = $row['data'];
     }
    if($val2 > $val1){
    $sql = "UPDATE data SET pre = '" .$val2. "'";
    if ($mysqli->query($sql) === TRUE) {

    }
     $reply['pressed'] = true;
     break;
    }
   sleep(1);
}
die(json_encode($reply);

和clicked.php:

<?php
$mysqli = new mysqli("localhost", "risicov19", "Edukapol19", "my_risicov19");
if ($mysqli->connect_errno) {
    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
$sql = "SELECT data FROM data";
$rs = mysqli_query($mysqli, $sql);
while($row = mysqli_fetch_assoc($rs)) {
    $val = $row['data'];
}
$agg = $val + 1;
$sql = "UPDATE data SET data = '" .$agg. "'";
    if ($mysqli->query($sql) === TRUE) {

    }
die(json_encode([ 'status' => 'success' ]));

您需要让 其他 用户知道其中一个用户何时单击了按钮。

正如@balzacLeGeek 观察到的,这是 Web 套接字的工作。但是您也可以在 AJAX 中执行此操作,使用暂停的 AJAX 调用或多或少像这样:

var refresher = function() {
    // CLIENT timestamp - beware of server time zones!
    const since = Date.now() / 1000;
    $.post('check-status.php', { since: since }).then(reply => {
        if (reply.pressed) {
            // do_reload();
        } else {
            // display some small animation to let user know we checked
        }
        // Schedule another round.
        window.setTimeout(refresher, 10);
    });
};

在页面中,当它加载时,只需调用 refresher() 它就会开始检查刷新。

检查状态函数被连续调用,这将导致系统负载不可接受。但是由于它 等待 服务器到 return,我们可以这样实现它:

<?php
    $reply = [ 'status' => 'success', 'pressed' => false ];

    for ($sec = 0; $sec < 60; $sec++) {
       // ... check whether anyone pressed the button ...
       if (file_exists('pressed.json')) {
           if (filemtime('pressed.json') > $_POST['since']) {
               // return immediately.
               $reply['data']    = json_decode(file_get_contents('pressed.json'), true);
               $reply['pressed'] = true;
               break;
           }
       }
       sleep(1);
    }
    header("Content-Type: application/json;charset=UTF-8");
    die(json_encode($reply);

通话 暂停 长达 60 秒或直到有人按下按钮;在这种情况下,一秒钟内,所有挂起的电话return,以及所有用户的屏幕重新加载;他们会立即发出另一个呼叫,等待下一次按下,依此类推。

您可能想玩一下暂停时间,或者实施一个 setInterval 看门狗,以确保正确发出刷新调用(如果一个调用失败,则该客户端的整个周期停止;客户端“死了”。所以在刷新时你设置一个全局时间戳变量,setInterval 看门狗函数验证时间戳永远不会早于暂停时间加上合理的余量,比如 2 秒。如果是,看门狗只是调用 refresher() 来重新启动循环,并且可能会显示一个简短的动画“您的 Internet 连接有问题”)。

按下函数只是创建一个文本文件以响应按钮按下。或者你可以使用数据库,或共享内存区域,或 Redis 或其他任何东西:

$('#button').on('click', ()=> {
    $.post('/clicked.php',
      {
          user: 'lserni', // or read from a global application object
          message: $('#message').val()
      }
});

脚本被调用,对于文件情况,你有一个竞争条件(如果两个人同时按下按钮怎么办?):

<?php
    $written = file_put_contents(
        'pressed.json',
        json_encode([
            'message' => $_POST['message'],
            'user'    => $_POST['user'],
            'date'    => date('d/m/Y H:i:s'),
        ]),
        LOCK_EX
    );

    header('Content-Type: application/json; charset=UTF-8');

    if (!$written) {
        die(json_encode([ 'status' => 'failure' ]));
    }

    die(json_encode([ 'status' => 'success' ]));

在文件的情况下,检查文件是否存在是不够的,因为在第一次点击后文件总是存在的,如果十个客户端检查,第一个不能简单地删除文件(其他九个什么也找不到,并假设没有人按下按钮)。

所以,每个客户端记录它最后一次运行按钮检查的时间,并且服务器回复创建新闻文件是否晚于请求的时间。这也不理想(上次时间没有保存,而是读取时钟,所以有一小段时间 window 不会检测到按下;并且客户端时间可能与服务器时间不同),但应该足够开始了。

简化版(刚刚测试)

这使用三个文件 poll.php、poll.html 和 click.php。每个客户端记录分配给最后一个答题器的随机标识符,并指示轮询器忽略该标识符。这样,轮询器将等待直到出现不同的标识符,这意味着有人点击了。

所有客户端都在同一页面上(如果同一页面打开超过 X 个连接,浏览器可能会报错,脚本将无法运行。我在这里使用了 3 个)。

poll.html:

<html>
<head>
        <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<style>
        div {
                display: inline-block;
                width: 150px;
                height: 3em;
                border: 1px solid red;
                padding: 2px;
        }
</style>
</head>
<body>
        <div><button></button><br /><input type="text" size="12" /></div>
</body>
<script>
        function freshener(clientName, x) {
                $.post('poll.php',
                        {
                                client: clientName,
                                ignore: x || 0
                        }
                )
                .then(reply => {
                        // Identify our client
                        let client = $('#'+clientName).closest('div');
                        client.find('input').val(reply.text);
                        window.setTimeout(function() { freshener(clientName, reply.ignore); }, 1);
                });
        }

        $(_=>{
                let btn = $('div').clone();
                $('div').remove();
                for (var i = 1; i < 4; i++) {
                        $('body').append(btn.clone().find('button').attr({ id: "x"+i }).text("X"+i).end());
                        // Create a poller for object x(i)
                        freshener("x"+i);
                }
                $('body').on('click', 'div', function(event) {
                        let clientName = $(this).find('button').attr('id');
                        $.post('click.php', { client: clientName });
                });
        });
</script>
</html>

poll.php:

<?php
    $reply = [ 'status' => 'success', 'pressed' => false, 'ignore' => $_POST['ignore'], 'text' => 'WAIT ' . date('H:i:s') ];

    $wait  = rand(2, 5);

    for ($sec = 0; $sec < $wait; $sec++) {
        if (file_exists('pressed.json')) {
            $data = json_decode(file_get_contents('pressed.json'), true);
            if ($data['ignore'] != $_POST['ignore']) {
               // return immediately.
               $reply['text']    = $data['text'];
               $reply['pressed'] = true;
               $reply['ignore'] = $data['ignore'];
               break;
           }
       }
       sleep(1);
    }
    header("Content-Type: application/json;charset=UTF-8");
    die(json_encode($reply));

最后是一个非常简单的 click.php:

error_reporting(E_ALL);
ini_set("display_errors", true);
// Someone clicked!
$time = date("H:i:s");
file_put_contents(
    'pressed.json',
    json_encode([
        'text' => "client {$_POST['client']}",
        'ignore' => floor(rand())
    ]),
    LOCK_EX
);

您可以手动调用 click.php 脚本来查看文件创建是否有错误。

当用户单击按钮时,您可以使用名为 redirect() 的 JavaScript 方法,此方法将重定向到您在重定向方法中提到的特定路径