简体   繁体   English

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

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

@LSerni I've edited the code using a db too but i'm still blocked:( @LSerni 我也使用数据库编辑了代码,但我仍然被阻止:(

It execute the clicked.php but the check status seems not working.它执行 clicked.php 但检查状态似乎不起作用。

I have 2 fields in a table, if the second one is higher then the first the page has to reload, but it isn't like this so far, the clicked.php file work fine.我在一个表中有 2 个字段,如果第二个字段高于第一个字段,则页面必须重新加载,但到目前为止还不是这样,clicked.php 文件工作正常。 check-status.php:检查状态.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);

and clicked.php:并点击。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' ]));

You need for the other users to know when one of them clicked the button.您需要让其他用户知道其中一个用户何时单击了该按钮。

As @balzacLeGeek observed, this is a job for Web sockets.正如@balzacLeGeek 所观察到的,这是 Web sockets 的工作。 But you can do it in AJAX too, using a suspended AJAX call more or less like this:但是您也可以在 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);
    });
};

In the page, when it is loaded, just call refresher() and it will start to, well, check for refresh.在页面中,当它被加载时,只需调用 refresher() ,它就会开始检查刷新。

The check-status function gets called continuously, which will cause an unacceptable load on the system.检查状态 function 被连续调用,这将导致系统负载不可接受。 But since it waits for the server to return, we can implement it like this:但是由于它等待服务器返回,我们可以这样实现它:

<?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);

The call is suspended for up to 60 seconds or until someone presses a button;通话暂停最多 60 秒或直到有人按下按钮; in that case, within one second, all the suspended calls return, and all the users' screen reload;在这种情况下,在一秒钟内,所有暂停的呼叫都返回,并且所有用户的屏幕都重新加载; and they immediately issue another call that will wait for the next press, and so on.他们立即发出另一个呼叫,等待下一次按下,依此类推。

You might want to play with the suspension time, or implement a setInterval watchdog that ensures that the refresher calls are properly issued (if one call fails, the whole cycle stops for that client; the client is "dead". So upon refresh you set a global timestamp variable, and the setInterval watchdog function verifies that the timestamp is never older than the suspension time plus a reasonable margin, say 2 seconds. If it is, the watchdog merely calls refresher() to restart the cycle, and maybe displays a brief animation "Your Internet connection had a problem").您可能想要使用暂停时间,或者实现一个 setInterval 看门狗,以确保正确发出刷新调用(如果一个调用失败,则该客户端的整个周期停止;客户端“死”了。所以在刷新时你设置全局时间戳变量,setInterval 看门狗 function 验证时间戳永远不会超过暂停时间加上合理的余量,例如 2 秒。如果是,看门狗只需调用 refresher() 重新启动循环,并可能显示一个简短 animation “您的 Internet 连接有问题”)。

The pressed function simply creates a text file in response to the button press.按下的 function 只是创建一个文本文件来响应按钮按下。 Or you can use a database, or a shared memory area, or Redis or whatever:或者您可以使用数据库,或共享 memory 区域,或 Redis 或其他任何东西:

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

The script gets called, and for the file case, you have a race condition (what if two people both press the button at the same time?):脚本被调用,对于文件案例,您有一个竞争条件(如果两个人同时按下按钮怎么办?):

<?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' ]));

In the case of the file, it was not enough to check for the file's existence, because after the first click the file always exists, and if ten clients check, the first cannot simply delete the file (the other nine would find nothing and assume nobody pressed the button).对于文件来说,仅仅检查文件是否存在是不够的,因为第一次点击后文件总是存在的,如果有十个客户端检查,第一个不能简单地删除文件(其他九个什么都找不到,并假设没有人按下按钮)。

So, each client records the last time it has run a button check, and the server replies whether a press file was created later than the requested time .因此,每个客户端都会记录它最后一次运行按钮检查的时间,并且服务器会回复是否在请求的时间之后创建了新闻文件 This too is not ideal (the last time is not saved but read off the clock, so there is a small time window when the press will not be detected; and the client time might be different from the server time), but it should be enough to start.这也不太理想(上次的时间不保存而是读了时钟,所以有一小段时间 window 不会检测到按下;并且客户端时间可能与服务器时间不同),但应该是足以开始。

Simplified version (just tested)简化版(刚刚测试)

This uses three files poll.php, poll.html and click.php.这使用了三个文件 poll.php、poll.html 和 click.php。 Each client records the random identifier assigned to the last clicker, and instructs the poller to ignore that identifier.每个客户端记录分配给最后一个点击者的随机标识符,并指示轮询器忽略该标识符。 This way, the poller will wait until a different identifier comes by, which means that somebody clicked.这样,轮询器将等到一个不同的标识符出现,这意味着有人点击了。

All clients are on the same page (browsers might complain if the same page opens more than X connections, and the script won't work. I used 3, here).所有客户端都在同一页面上(如果同一页面打开超过 X 个连接,浏览器可能会抱怨,并且脚本将不起作用。我在这里使用了 3)。

poll.html:轮询.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:

<?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));

and finally a very simple click.php:最后是一个非常简单的点击。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
);

You can call manually the click.php script to see whether there are errors in the file creation.可以手动调用click.php脚本查看文件创建是否有错误。

You can use a JavaScript method called redirect() when a users click on a button this method will redirect to the particular route which you have mention in your redirect method当用户单击按钮时,您可以使用名为 redirect() 的 JavaScript 方法,此方法将重定向到您在重定向方法中提到的特定路线

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM