I have written a small widget using PHP and AJAX that fetches real time information from a MySQL database every 10 seconds. The problem is that after a number of successful runs it tends to become buggy. It no longer respects the 10 seconds interval and even the time counter at the end of the widget tends to "jump" a number of seconds. The files look as it follows:
MySQL class: The database.class.php file contains the one single function which helps me connect to MySQL using PDO.
The Device class:
(as illustrated below) contains one function that helps me retrieve the last 10 entries from the database. The readings_$id
(where $id
is a number) table gets updated frequently.
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();
}
}
}
The widget file: (attached bellow) creates a new device object, gets the id from the session variable and then gets the last ten entries using the mysql function above. After this finishes I set my object to null, since the operation will repeat again 10 seconds later. The file init.core.php
contains the session_start, important included classes (such as the database), and important application constants (such as the $id_device
stored inside a SESSION).
<?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>
The jQuery / AJAX script:
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);
Finally there is the index.php file:
<?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');
?>
The script works fine at the beginning but then it starts to malfunction (either hang or get buggy). Even the time at the bottom of the widget which shows when the information was last fetched from the database tends to refresh at an arbitrary amount of seconds which is not the one I given in the AJAX script. Did anyone encounter this issue before?
P.S: Sorry for the very long read.
Kindly, Radu
It does not respect the 10 seconds exactly because of this pattern:
function get_reads() {
AJAX.post
.success(function() {
get_reads(); // with a 10 seconds delay from setTimeout
})
}
That peace of code will execute get_reads
10 seconds after the response of AJAX.post
comes, not after you last called get_reads
.
So first think about fixing that.
Second problem, the hanging, is caused because you are mixing that recursive function with setInterval
.
If you read the documentation you'll find out that setInterval
calls the function repeatedly, once each X milliseconds (10000ms -> 10 seconds).
So you are running get_reads
every 10 seconds through setInteval
and each time you call it you also launch an infinite recursion loop through get_reads
itself.
Stick to setInterval
and remove that recursive call (setTimeout(function(){get_reads();}, 10000);
) and you'll fix both the problems.