LONG POLLING (in php) starts hanging after 5 requests to database - php

I'm developing live auction site, with real-time bidding system. I'm using LONG POLLING when user bids on item. I've chose long polling because WebSockets are not yet very supported and NODEJS is to complicated for me to implement right now. So I'm stuck with this simle ajax long polling, which works great for about five bids.
So the problem is: Bidding works great for 5-6 item bids in 1 second intervals (I get instant response from server-ajax), but the 7th (click) on bid button this response-long polling hangs for about 16-22 seconds and then completes the request. At the end everything is updated in database and completed but after every 5-6 bids response/ajax call hangss for about 16-22 seconds.
How could I reduce this time, that everything should go smoothly no matter how many times user bids, without lag...
I'm using Apache/PHP/MySql on localhost/wamp
My code:
index.php
<script type="text/javascript" charset="utf-8">
var old_timestamp = <?php echo $old_timestamp;?>; //here i'm echoing last timestamp of auction
function waitForMsg(){
jq.ajax({
type: "POST",
url: "http://localhost/bid/comet/poll.php",
data: {"old_timestamp" : old_timestamp},
async: true,
cache: false,
success: function(data){
var json = eval('(' + data + ')');
if(json['msg'] != "") {
jq('#comet_display').html(json['msg']); //here I show ID of which auction item was bidded
}
old_timestamp = json['old_timestamp'];
setTimeout('waitForMsg()',100);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
setTimeout('waitForMsg()',1000);
}
});
}
jq(window).load(function(){
waitForMsg();
jq("#a_loader").show();
var url = "http://localhost/bid/auctions-ajax"; // the script where you handle the form input.
jq.ajax({
type: "POST",
url: url,
data: {au978 : true},
async:false, //to sem dodal za Ĩasovni zamik
success: function(data)
{
jq("#a_loader").hide();
jq("#show-category").html(data); // show response from the php script.
},
error: function(result) {
jq("#show-category").html("Sorry, something went wrong. Please try again later.");
}
});
});
function bid(id){
var url = "http://localhost/bid/comet/update-auction.php"; // the script where you handle the form input.
var user_id=<?php echo $user_id;?>; //user id from session
jq.ajax({
type: "POST",
url: url,
data: {"auct_id" : id, "user_id" : user_id}, // serializes the form's elements.
success: function(data)
{
//it updates in user table its remaining number of bids
},
error: function(XMLHttpRequest, textStatus, errorThrown){
alert("Something went wrong. Click OK to refresh.");
}
});
}
</script>
poll.php
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
require_once($_SERVER['DOCUMENT_ROOT'] . 'bid/include/DEFINES.php');
require_once(CLASS_AUCTION);
require_once(CLASS_DB);
$a=new Auction();
$old_timestamp = $_POST['old_timestamp'];
$bidded_id=0;
$db=DB::getInstance();
$sql="SELECT timestamp, id FROM auction ORDER BY timestamp DESC LIMIT 1"; //desno doda tabelo kategorija
$stmt=$db->db->prepare($sql) or die("Prepare Error");
$stmt->execute();
$result2=$stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($result2 as $rez){
$current_timestamp=$rez['timestamp'];
$bidded_id=$rez['id'];
}
$stmt->closeCursor();
while($current_timestamp <= $old_timestamp){
usleep(1000);
clearstatcache();
$db=DB::getInstance();
$sql="SELECT timestamp, id FROM auction ORDER BY timestamp DESC LIMIT 1";
$stmt=$db->db->prepare($sql) or die("Prepare Error");
$stmt->execute();
$result=$stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($result as $rez){
$current_timestamp=$rez['timestamp'];
$bidded_id=$rez['id'];
}
$stmt->closeCursor();
}
$response = array();
$response['msg'] = 'BID na avkciji: '.$bidded_id;
$response['old_timestamp'] = $current_timestamp;
echo json_encode($response);
}else{
require_once($_SERVER['DOCUMENT_ROOT'] . 'bid/errors/404.html');
}
?>
and the update-auction.php
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
require_once($_SERVER['DOCUMENT_ROOT'] . 'bid/include/DEFINES.php');
require_once(CLASS_AUCTION);
require_once(CLASS_USER);
require_once(CLASS_DB);
$u=new User();
$a=new Auction();
$auction_id=$_POST['auct_id'];
$user_id=$_POST['user_id'];
$date = new DateTime();
$timestamp=$date->getTimestamp();
$a->updateAuction($auction_id,$user_id,$timestamp/*,$bid_price,$bids_spent,$total_paid*/);
$u->updateUserBids($user_id);
}else{
require_once($_SERVER['DOCUMENT_ROOT'] . 'bid/errors/404.html');
}
?>
Thank you for viewing my problem!

Consider switching to WebSockets. It was designed to fix the long polling issue.

Ok, I have find a solution which fixes this 17-22 seconds LAG-HANGING problem. Now it's almost instant, regardless how many times you click. But I'm still not sure, if this is the best solution of long polling.
I'm posting it, if someone would have the same problem.
I've changed LONG POLLING function in my poll.php to this:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
require_once($_SERVER['DOCUMENT_ROOT'] . 'bid/include/DEFINES.php');
require_once(CLASS_AUCTION);
require_once(CLASS_DB);
$a=new Auction();
$db=DB::getInstance();
$sql="SELECT timestamp, id, last_username FROM auction ORDER BY timestamp DESC LIMIT 1";
$response = array();
while(1)
{
$stmt=$db->db->prepare($sql) or die("Prepare Error");
$stmt->execute();
$result=$stmt->fetch(PDO::FETCH_ASSOC);
if (!empty($result)){
$current_timestamp=$result['timestamp'];
$response['msg'] = 'New BID';
$response['old_timestamp'] = $current_timestamp;
echo json_encode($response);
break;
}
sleep(3000);
clearstatcache();
}
}else{
require_once($_SERVER['DOCUMENT_ROOT'] . 'bid/errors/404.html');
}
?>
and now i'm polling in my index.php like this:
<?php
$db=DB::getInstance();
$sql="SELECT timestamp FROM auction ORDER BY timestamp DESC LIMIT 1";
$stmt=$db->db->prepare($sql) or die("Prepare Error");
$stmt->execute();
$result2=$stmt->fetch(PDO::FETCH_ASSOC);
$old_id=0;
$last_timestamp=$result2['timestamp'];
?>
<script type="text/javascript" charset="utf-8">
var last_timestamp = <?php echo $last_timestamp;?>;
var old_timestamp=0;
function waitForMsg(){
jq.ajax({
type: "POST",
url: "http://localhost/bid/comet/poll.php",
async: true,
cache: false,
success: function(data){
var json = eval('(' + data + ')');
if(old_timestamp==0 || last_timestamp==old_timestamp){
}else{
if(json['msg'] != "") {
jq('#comet_display').html(json['msg']);
}
}
old_timestamp = json['old_timestamp'];
setTimeout('waitForMsg()',500);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
setTimeout('waitForMsg()',1000);
}
});
}
jq(window).load(function(){
waitForMsg();
});
function bid(id){
var url = "http://localhost/bid/comet/update-auction.php"; //here I update auction and user's bids
var user_id=<?php echo json_encode($user_id);?>;
var user_name=<?php echo json_encode($user_name); ?>;
jq.ajax({
type: "POST",
async: true,
cache: false,
url: url,
data: {"auct_id" : id, "user_id" : user_id, "username" : user_name}, // serializes the form's elements.
success: function(data)
{
setTimeout('waitForMsg()',100);
var cnt = parseInt(jq(".db_bids").text());
if (!isNaN(cnt))
{
cnt--;
jq(".db_bids").text(String(cnt));
}
},
error: function(XMLHttpRequest, textStatus, errorThrown){
alert("Something went wrong. Click OK to refresh.");
}
});
}
</script>
I'm still developing this on localhost & will see how this behaves on real server with 100+ users.
If anyone have better and faster solution with LONG POLLING from databases, please let me know :)

Related

jQuery Ajax Json response - check if is null

I am getting data from MySQL using jQuery Ajax and JSON. However I need to know when the response is empty. I passe a date parameter to my php that will return some data or not... depending on date.
My Javascript code (simple version):
function pac_irra(date){
.ajax({
url: 'get_db_data/pac_irra.php?date='+date,
dataType: 'JSON',
type: 'POST',
data: {get_values: true},
beforeSend: function(){
$("#morris-line-chart").append(load_img);
},
success: function(response) {
date = response[0].Timestamp;
$('#a1').append(date);
},
});
}
If for example I used yesterday (2015-09-26) data I get the following json data (only a part of it):
[{"Timestamp":"2015-09-26 16:50:00","pac":"35.20","irra":"38.97"},{"Timestamp":"2015-09-26 17:00:00","pac":"32.19","irra":"35.51"}]
Now, for example, if I chose a date without data it returns:
[]
In my javascript code below I would like to add a if statement to my success function in case of json array is empty... something like:
function pac_irra(date){
.ajax({
url: 'get_db_data/pac_irra.php?date='+date,
dataType: 'JSON',
type: 'POST',
data: {get_values: true},
beforeSend: function(){
$("#morris-line-chart").append(load_img);
},
success: function(response) {
date = response[0].Timestamp;
$('#a1').append(date);
if ( ***array is empty***) {
('#a1').append('No data');
};
},
});
}
In my success function I have a morris chart created with the json data... I don't put it in the code...
So how do I check if it's empty? I already made a lot of attempts:
if (response.length == 0)
or another attempt
if (response[0].Timestamp == "") or if (!response)
And nothing works... I still can't check if the json array is empty...
My php code:
<?php
error_reporting(0);
$path = $_SERVER['DOCUMENT_ROOT'];
$path .= "/database/db_connect.php";
include_once($path);
if(isset($_GET['date'])) {
$date = $_GET['date'];
$days = $_GET['days'];
$var = array();
$query = "SELECT CONVERT_TZ(CONCAT(Date,' ',pac.Time), 'UTC', 'Europe/Lisbon' ) as Timestamp, ROUND((pac.Value/6440)*100,2) pac, ROUND((irra.Value/1000)*100,2) irra
FROM AggData pac
LEFT JOIN (SELECT Time, Value
FROM AggData WHERE Date=DATE_ADD('$date',INTERVAL '$days' DAY) and idEquipment=5 and idMeasure=6 ) irra
ON pac.Time=irra.Time
Where pac.Date=DATE_ADD('$date',INTERVAL '$days' DAY) and pac.idEquipment=1 and pac.idMeasure=3
AND (irra.Value>0 or pac.Value>0)
Order BY pac.Time asc
" or die("Error in the consult.." . mysqli_error($link));
$result = $link->query($query);
while($obj = mysqli_fetch_object($result)) {
$var[] = $obj;
}
echo json_encode($var);
}
?>
Try below if will check various condition
if((response && jQuery.isArray(response))?(response.length==0?false:(jQuery.isPlainObject(response[0])?!jQuery.isEmptyObject(response[0]):response[0])):response){
//console.log("adfdsaf");
}
if it will check if
response is null or undefined
or response == []
or response == [{}] or response[""]
I think this is the problem
success: function(response) {
if((response && jQuery.isArray(response))?(response.length==0?false:(jQuery.isPlainObject(response[0])?!jQuery.isEmptyObject(response[0]):response[0])):response){
('#a1').append('No data');
}else{
date = response[0].Timestamp;
$('#a1').append(date);
}
};
},
hopefully it will work

Ajax data function that should work but doesn't

Within my application I have an Ajax function that adds information to a database. Everything worked perfectly until I added in 2 more parameters which was location and username.
It still works with everything else but it doesn't add those last 2 into the database. The names of within the database is location and username. assignedUsername and storeLocation are set else where in the code.
Ajax:
$("#send").click(function(){
$.ajax({
type: 'POST',
contentType: "application/json",
data: orderFood(),
url: rootURL + "/orderFood",
dataType: "json",
success: function(data)
{
alert(assignedUsername);
alert("Data Added");
$.mobile.changePage("#mainMenu");
},
error: function(data)
{
alert(assignedUsername);
alert("Data NOT Added");
$.mobile.changePage("#mainMenu");
}
});
});
function orderFood()
{
alert(storeLocation + ", " + assignedUsername);
return JSON.stringify({
"food1": food1,
"food2": food2,
"food3": food3,
"food4": food4,
"food5": food5,
"food6": food6,
"food7": food7,
"food8": food8,
"food9": food9,
"location": storeLocation,
"username": assignedUsername
});
}
PHP:
$app->post('/orderFood/', 'orderFood');
function orderFood()
{
$request = \Slim\Slim::getInstance()->request();
$q = json_decode($request->getBody());
$sql = "INSERT INTO subsordered(food1, food2, food3, food4, food5, food6, food7, food8, food9, location, username) VALUES (:food1, :food2, :food3, :food4, :food5, :food6, :food7, :food8, :food9, :location, :username)";
try
{
$db = getConnection();
$stmt=$db->prepare($sql);
$stmt->bindParam("food1",$q->food1);
$stmt->bindParam("food2",$q->food2);
$stmt->bindParam("food3",$q->food3);
$stmt->bindParam("food4",$q->food4);
$stmt->bindParam("food5",$q->food5);
$stmt->bindParam("food6",$q->food6);
$stmt->bindParam("food7",$q->food7);
$stmt->bindParam("food8",$q->food8);
$stmt->bindParam("food9",$q->food9);
$stmt->bindParam("location",$q->location);
$stmt->bindParam("username",$q->username);
$stmt->execute();
$db = null;
}
catch(PDOException $e){
echo $e->getMessage();
}
}
I know the PHP is correct though testing with cURL but I thought I'd include it just to get the whole picture
I am extremely stuck with this, from what I can see it SHOULD work but it just doesn't

ajax and php to load more content from mysql when page gets to bottom

I've seen some answers to this question on this site already, but i still haven't been able to implement it as i want to for 2 days now. I'm sort of a beginner so a very clear explanation would be of great help,
i have a mysql database of some data, i want to read from a table and display 30 rows at a time, when the user scrolls to the end of the page, i want to load another 30 rows (i have been able to do the first 30, but loading the remaining is a challenge for me).
i already have this:
$(document).ready(function(){
$(window).scroll(function() {
if($(window).scrollTop() == $(document).height() -$(window).height()) {
//ive tried all sorts of things here it just doesnt work
}
});
also an example of the php file that loads the next contents would help,
i'm using php and mysqli
thanks a lot in advance.
so this is my loadmore.php, its for the functionality, haven't styled the output:
<?php
require_once 'functions.php'; //my databse connection is in this file
//i created a function queryMysql($query) in functions.php, thats what is used here
$result = queryMysql("SELECT * FROM articles WHERE live='1' ORDER BY created DESC LIMIT $start, 30");
$num = $result->num_rows;
for ($j = 0 ; $j < $num ; ++$j){
$row = $result->fetch_array(MYSQLI_ASSOC);
$title = $row['title'];
$subtitle = $row['subtitle'];
echo "$title<br />$subtitle";
}?>
for the ajax, i changed it to the first answer i got here, but all my attempts have looked like this:
$(window).scroll(function() {
if($(window).scrollTop() == $(document).height() - $(window).height()) {
$.ajax({
type: method,
data: {}, //Your data
url: 'loadmore.php',
async: true,
success: function (data, textStatus, jqXHR) {
$('#article-inro-hold').append(data);
},
error: function (jqXHR) {
//Error handler
}
});
}
});
Try to implement jquery ajax, something rough like this:
$(document).ready(function () {
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
$.ajax({
type: method,
data: {}, //Your data
url: 'your/url/to/get/more/content/from',
async: true,
success: function (data, textStatus, jqXHR) {
$('#myDiv').append(data);
},
error: function (jqXHR) {
//Error handler
}
});
}
});
});
You have to make an ajax call for each time, when you scroll amount get up, nearer to document height. Along with you also have to manage your offset, otherwise you will get duplicate records (You can use hidden field for that), and pass it each time in your ajax call.
<div id="ajax-response"></div>
<input type="hidden" value="0" id="offset" />
<script>
$(document).ready(function(){
$(window).scroll(function() {
if($(window).scrollTop() == $(document).height() - $(window).height()) {
$.ajax({
url: 'requesthandler.php',
type: 'post',
data: {
task: 'show-more',
offset: document.getElementById('offset').value
},
success: function(response){
jsonObj = $.parseJSON(response);
$('#ajax-response').append(jsonObj.html);
document.getElementById('offset').value = jsonObj.offset;
}
})
}
});
});
and requesthandler.php will look like:
if($_POST['task'] == 'show-more'){
$offset = (int) $offset;
$sql = "SELECT * FROM table limit $offset, 10";
$data = '';
foreach ($conn->query($sql) as $row) {
$data .= "<div>$row['column']</div>";
}
echo json_encode(array(
'offset' => ($offset + 10),
'html' => $data,
))
}
$query = $db->query("SELECT * FROM bags ORDER BY id DESC LIMIT 7");
Can we use $_POST here to get only needed information.
$limit=($_POST["bag"]);
$query = $db->query("SELECT * FROM bags WHERE id = '.$limit.' ORDER BY id DESC LIMIT 7");

Why is my long polling code for a notification system not updating in real time? PHP MYSQL

I am making a notification system similar to the red notification on facebook. It should update the number of messages sent to a user in real time. When the message MYSQL table is updated, it should instantly notify the user, but it does not. There does not seem to be an error inserting into MYSQL because on page refresh the notifications update just fine.
I am essentially using code from this video tutorial: http://www.screenr.com/SNH (which updates in realtime if a data.txt file is changed, but it is not written for MYSQL like I am trying to do)
Is there something wrong with the below code:
**Javascript**
<script type="text/javascript">
$(document).ready(function(){
var timestamp = null;
function waitForMsg(){
$.ajax({
type: "GET",
url: "getData.php",
data: "userid=" + userid,
async: true,
cache: false,
success: function(data){
var json = eval('(' + data + ')');
if (json['msg'] != "") {
$('.notification').fadeIn().html(json['msg']);
}
setTimeout('waitForMsg()',30000);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
setTimeout('waitForMsg()',30000);
}
});
}
waitForMsg();
</script>
<body>
<div class="notification"></div>
**PHP***
<?php
if ($_SERVER['REQUEST_METHOD'] == 'GET' )
{
$userid = $_GET['userid'];
include("config.php");
$sql="SELECT MAX(time) FROM notification WHERE userid='$userid'";
$result = mysql_query($sql);
$row = mysql_fetch_assoc($result);
$currentmodif = $row['MAX(time)'];
$s="SELECT MAX(lasttimeread) FROM notificationsRead WHERE submittedby='$userid'";
$r = mysql_query($s);
$rows = mysql_fetch_assoc($r);
$lasttimeread = $rows['MAX(lasttimeread)'];
while ($currentmodif <= $lasttimeread) {
usleep(10000);
clearstatcache();
$currentmodif = $row['MAX(time)'];
}
$response = array();
$response['msg'] = You have new messages;
echo json_encode($response);
}
?>
there is a problem with your javascript line below
url: "getData.php",
data: "userid" + userid,
async: true,
remove the = sign and try again.
i have not read the whole code but found this is the cause test and feel free to reply if still got more issues.
You're not re-executing the SQL statement in the loop so the value in "$row['MAX(time)']" is never going to change.
If you re-execute the query in the loop this example may work--but executing a query every 10ms is not going to be a very efficient way to implement real-time notification.
Also, if the PHP script runs longer then the time configured in php.ini (max_execution_time, 30 secs by default), you'll get an error.

Echoed Javascript appearing in alert instead of processing

I have created a registration system that uses AJAX to process the form so that I can return false. The relevant js is the top block of code. I pass this data to join.php, which sends it to the database. I run a check in join.php to make sure that nobody with a duplicate email has already signed up. As you can see, if the email already exists, I want to insert a message using javascript. Instead of reading the script tags, it simply pastes them into my alert in plaintext...so my alert has the datastring and then actually says the code <script>...</script>. How can I get this js to process instead?
Javascript:
$(".submit").click(function() {
var dataString = {
school : $("#school").val(),
studentEmail : $("#studentEmail").val(),
studentPassword : $("#studentPassword").val(),
parentEmail : $("#parentEmail").val(),
parentPassword : $("#parentPassword").val(),
studentFirstName : $("#studentFirstName").val(),
studentLastName : $("#studentLastName").val(),
studentPhone : $("#studentPhone").val(),
parentFirstName : $("#parentFirstName").val(),
parentLastName : $("#parentLastName").val(),
parentPhone : $("#parentPhone").val()
};
$.ajax({
type: "POST",
url: "join.php",
data: dataString,
success: function(data) {
alert ("data sent: "+ data);
}
});
return false;
}
});
join.php
if($_POST) {
$school = mysql_real_escape_string($_POST['school']);
$studentEmail = mysql_real_escape_string($_POST['studentEmail']);
$parentEmail = mysql_real_escape_string($_POST['parentEmail']);
$studentFirstName = mysql_real_escape_string($_POST['studentFirstName']);
$studentLastName = mysql_real_escape_string($_POST['studentLastName']);
$studentPhone = mysql_real_escape_string($_POST['studentPhone']);
$parentFirstName = mysql_real_escape_string($_POST['parentFirstName']);
$parentLastName = mysql_real_escape_string($_POST['parentLastName']);
$parentPhone = mysql_real_escape_string($_POST['parentPhone']);
$check = mysql_query("SELECT studentEmail FROM clients WHERE studentEmail = '{$studentEmail}';");
$num = mysql_num_rows($check);
if (($num) == 0) {
$sql = "INSERT INTO clients ".
"(`studentEmail`, `studentPassword`, `parentEmail`, `parentPassword`, ".
"`studentFirstName`, `studentLastName`, `studentPhone`, `parentFirstName`, ".
"`parentLastName`, `parentPhone`, `school`) ".
" VALUES ('$studentEmail', '$studentPassword', '$parentEmail', ".
"'$parentPassword', '$studentFirstName', '$studentLastName', ".
"'$studentPhone', '$parentFirstName', '$parentLastName', '$parentPhone', '$school')";
$result = mysql_query($sql);
if ($result) {
echo "Database query successful!";
}
else {
die("Database query failed: " . mysql_error());
}
include "emails/signUp.php";
}
else {
echo 'FAIL
<script>
$(".formErrorMessage").html("Email already exists");
</script>';
}
}
The alert shows your script block because you've got this in your success handler:
alert ("data sent: "+ data);
Data is going to be whatever text you output in your PHP. If you want to have variable behavior based on whether your request was successful or not, I'd recommend that your PHP returns JSON containing a success flag and the message. Your JavaScript callback would then look like this:
function(data) {
if (data.success) {
alert ("data sent: "+ data.message);
} else {
$(".formErrorMessage").text(data.message);
}
}
Your PHP should then change your content-type to JSON:
header('Content-Type: application/json');
... and your echos would change to something like this:
echo '{"success": false, "message": "Email already exists."}';
Your server call shouldn't be returning raw HTML. Should return JSON that contains all the status information the server needs to handle things. i.e. in the usual case:
{'success': true}
or
{'success': false, 'emailAlreadyExists': true, 'msg': 'Email Already Exists'}
of
{'success': false, 'msg': 'Database query failed: blahblahMySqlError'}
Then your client JS should handle it...
$.ajax({
type: "POST",
url: "join.php",
data: dataString,
success: function(data) {
if(data.success) {
alert ("success!");
}
else{
alert("error: " + data.msg);
if(data.emailAlreadyExists){
$(".formErrorMessage").html("Email already exists");
}
}
}
});
from php, you have give formatted status responses
on success:
echo '{"status":"success", message:"Database query successful!"}';
if account already exists:
echo '{"status":"failed", message:"Email already exists"}';
So you will be able to identify this in JavaScript callback function
$.ajax({
type: "POST",
url: "join.php",
data: dataString,
success: function(data) {
if(status.error == "failed"){
$(".formErrorMessage").html(data.message);
}
}
});
This is the best way to do it. Or if you just want to execute a string received from php, you can use eval
success: function(data) {
eval(data);
}
In that case there is no need of script tags in response, only the Javascript statement that has to be executed.

Categories