【问题标题】:Real time application with PHP and AJAX tends to hang and not respect the refresh interval使用 PHP 和 AJAX 的实时应用程序往往会挂起并且不遵守刷新间隔
【发布时间】:2014-10-16 09:21:24
【问题描述】:

我使用 PHP 和 AJAX 编写了一个小部件,它每 10 秒从 MySQL 数据库中获取实时信息。问题是,在多次成功运行后,它往往会出现故障。它不再尊重 10 秒的间隔,甚至小部件末尾的时间计数器也倾向于“跳跃”几秒钟。文件如下所示:

MySQL 类: database.class.php 文件包含一个函数,它可以帮助我使用 PDO 连接到 MySQL。

设备类: (如下图所示)包含一个函数,可以帮助我从数据库中检索最后 10 个条目。 readings_$id($id 是一个数字)表会经常更新。

require_once dirname(__FILE__).'/database.class.php';

class Device extends Database {

    public function get_last_ten_reads($id){

        $table = "readings_".$id;
        try {
            $statement = $this->connection->prepare("SELECT * FROM $table ORDER BY server_time DESC LIMIT 10");
            //Execute the statement:
            $statement->execute();
            //Get the result:
            $result = $statement->fetchAll(PDO::FETCH_ASSOC);

            return $result;
        } catch (PDOException $exception) {
            echo $exception -> getMessage();
        }
    }

}

小部件文件:(附在下面)创建一个新的设备对象,从会话变量中获取 id,然后使用上面的 mysql 函数获取最后十个条目。完成此操作后,我将对象设置为 null,因为该操作将在 10 秒后再次重复。文件 init.core.php 包含 session_start、重要的包含类(例如数据库)和重要的应用程序常量(例如存储在 SESSION 中的 $id_device)。

<?php include_once($_SERVER['DOCUMENT_ROOT'].'/core/init.core.php');?>
<?php $device    = new Device();?>
<?php $id_device = $_SESSION['account']['id']; ?>
<?php $entries   = $device->get_last_ten_reads($id_device); ?>
<div class="panel panel-default">
    <div class="panel-heading">
        <h3 class="panel-title">Last 10 readings:</h3>
    </div>
    <div class="table-responsive">
        <table class="table table-hover">
            <thead>
                <tr class="active">
                    <th>Id Sensor:</th>
                    <th>Sensor Time:</th>
                    <th>Server Time:</th>
                    <th>Value:</th>
                    <th>Battery level:</th>
                </tr>
            </thead>
            <tbody>
                <?php              
                foreach ($entries as $row) { 
                ?>
                    <tr>
                        <td><?php echo $row['id_sensor'];?></td>
                        <td><?php echo $row['sensor_time'];?></td>
                        <td><?php echo $row['server_time'];?></td>
                        <td><?php echo $row['value'];?></td>
                        <td><?php echo $row['battery_level'];?></td>
                    </tr>  

                <?php } ?>
            </tbody>
        </table>
    </div>
    <?php $device = null;?>
    <div class="panel-footer">
        <small>Last updated at: 
            <?php date_default_timezone_set('Europe/London');
            $date = date('Y-m-d H:i:s');
            echo $date ?>
        </small>
    </div>
</div>

jQuery / AJAX 脚本:

function get_reads(){
    var reads = $.ajax({
        type: "POST",
        url: ".././cards/widget.php",
        async: false,
        cache: false
    }).success(function(){
        setTimeout(function(){get_reads();}, 10000);
    }).responseText;

    $('.bootcards-list').html(reads);
}
setInterval(function(){get_reads();}, 10000);

终于有了index.php文件:

<?php
    include ('core/init.core.php');
    include ('header.php');
?>
<!-- Begin page content -->
<div class="container">
    <div class="row">
        <div class="col-sm-12 bootcards-list">
            <?php include('cards/widget.php');?>
        </div>

        <script type="text/javascript" src="js/ajax.js"></script>

    </div> <!-- /row -->
</div>

<?php
    include ('footer.php');
?>

该脚本在开始时运行良好,但随后开始出现故障(挂起或出现故障)。即使是显示上次从数据库中获取信息的时间的小部件底部的时间也倾向于以任意秒数刷新,这不是我在 AJAX 脚本中给出的秒数。以前有人遇到过这个问题吗?

P.S:很抱歉读了这么久。

请, 拉杜

【问题讨论】:

  • 您在 AJAX 函数上同时执行了 setInterval 和 setTimeout。您应该使用其中一个或另一个,如果您同时使用两个,那么您将触发两个请求,每 10 秒一个(setInterval)和一个每 10 + 时间执行一次(setTimeout)

标签: php jquery ajax oop real-time


【解决方案1】:

由于这种模式,它不尊重 10 秒:

function get_reads() {
    AJAX.post
          .success(function() {
              get_reads(); // with a 10 seconds delay from setTimeout
          })
}

代码的和平将在AJAX.post 的响应到来后 10 秒执行get_reads,而不是在您最后一次调用get_reads 之后。 所以首先考虑解决这个问题。

第二个问题,挂起,是因为您将递归函数与setInterval 混合在一起。

如果您阅读文档,您会发现setInterval 重复调用该函数,每 X 毫秒(10000 毫秒 -> 10 秒)一次。 因此,您每 10 秒通过 setInteval 运行一次 get_reads,并且每次调用它时,您还会通过 get_reads 本身启动一个无限递归循环。

坚持setInterval 并删除该递归调用 (setTimeout(function(){get_reads();}, 10000);),您将解决这两个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-25
    • 2012-01-10
    • 2015-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多