Ajax to PHP Looping Issue - php

I have an issue with a continuous Ajax to PHP loop. The code (below) works absolutely fine. However I find it will run for 2, 3, or more hours or as required.. but then have an "x minute" break where it won'T run or produce any logs... before once "again" resuming for 2, 3 or more hours.
$.ajax({
async: false,
type: "POST",
url: ajaxURL,
dataType: 'json',
data: {functionname: 'conditionTrade', arguments: [c_piars, c_timeframes, usd_amount ,stop_loss, stop_loss_min, stop_loss_max]},
// post to php and check condition
success: function (data) {
if( !('error' in data) ) {
var results = data["result"];
if (results) {
$( "#tradelog" ).load( "tradelog.html" ); // <--- produce a log
var pft = c_piars+"profitloss.txt";
$( "#profit" ).load( pft );
checkCondition();
// recursion call to this same method ie. check again
}
else {
console.log(data.error);
}
var objDiv = document.getElementById("tradelog");
objDiv.scrollTop = objDiv.scrollHeight;
}},
error: function(jqXHR, textStatus, errorThrown) {
console.log("Error[refresh]: " + textStatus);
console.log(jqXHR);
checkCondition();
// recursion call to this same method ie. check again
},
});
Please can somebody advise as to why this loop is randomly breaking, and then continuing on its own.
The loop is intended to retrieve candlestick data (approximately every 5 seconds), then perform some Technical Analysis checks, before finally.. outputing a log of the whether the TA conditions were found. The code runs fine.
However it's almost as if when I'm not physically on the browser page, then, it may randomly stop working for 15 minutes or a random time, before resuming on its own. (Hence I may get 2,3,4,5 hours of continuous checks, then a random dropout of 30 minutes to 2 hours, before resuming checks for x hours). What am I missing? I've looked into using different browsers, browser resources, internet connections, php timeouts etc. but this one is really head scratching. Thank you if you can help.
Ps. With a previous version I used to used the ajax- settimeout (5000) looping method, rather than the "recursion call to this same method" shown. This would literally run all day night without any dropping out - but I found that it would race itself from time to time, not waiting for the previous loop to complete. And therefore I might find 2 or 3 log entries for the same loop. How might I stabalize this loop to perform as I would like ? Thanks.

If you have similar: How can I make setInterval also work when a tab is inactive in Chrome?
If your script/jsfiddle is logging to the console, simply route it to the page title eg. document.title= 'your setInterval output'; ..so you'll better be able to detect what your interval loop is doing as you switch tab etc.

Related

PHP jQuery Long Polling Chat Application

I've made a simple PHP jQuery Chat Application with Short Polling (AJAX Refresh). Like, every 2 - 3 seconds it asks for new messages. But, I read that Long Polling is a better approach for Chat applications. So, I went through some Long Polling scripts.
I made like this:
Javascript:
$("#submit").click(function(){
$.ajax({
url: 'chat-handler.php',
dataType: 'json',
data: {action : 'read', message : 'message'}
});
});
var getNewMessage = function() {
$.ajax({
url: 'chat-handler.php',
dataType: 'json',
data: {action : 'read', message : 'message'},
function(data){
alert(data);
}
});
getNewMessage();
}
$(document).ready(getNewMessage);
PHP
<?php
$time = time();
while ((time() - $time) < 25) {
$data = $db->getNewMessage ();
if (!empty ($data)) {
echo json_encode ($data);
break;
}
usleep(1000000); // 1 Second
}
?>
The problem is, once getNewMessage() starts, it executes unless it gets some response (from chat-handler.php). It executes recursively. But if someone wants to send a message in between, then actually that function ($("#submit").click()) never executes as getNewMessage() is still executing. So is there any workaround?
I strongly recommend that you read up on two things: the idea behind long polling, and jQuery callbacks. I'll quickly go into both, but only in as much detail as this box allows me to.
Long polling
The idea behind long polling is to have the webserver artificially "slow down" when returning the request so that it waits until an event has come up, and then immediately gives the information, and closes the connection. This means that your server will be sitting idle for a while (well, not idle, but you know what I mean), until it finally gets the info that a message went through, sends that back to the client, and proceeds to the next one.
On the JS client side, the effect is that the Ajax callback (this is the important bit) is delayed.
jQuery .ajax()
$.ajax() returns immediately. This is not good. You have two choices to remedy this:
bind your recursion call in the success and error callback functions (this is important. the error function might very well come up due to a timeout)
(see below):
Use This:
var x = $.ajax({blah});
$.when(x).done(function(a) { recursiveCallHere(); });
Both amount to the same thing in the end. You're triggering your recursion on callback and not on initiation.
P.S: what's wrong with sleep(1)?
In long polling new request should be initiated when you have received the data from the previous one. Otherwise you will have infinite recursion in browser freezing.
var getNewMessage = function() {
$.ajax({
url: 'chat-handler.php',
dataType: 'json',
data: {action : 'read', message : 'message'},
success: function(data) {
alert(data);
getNewMessage(); // <-- should be here
}
});
}

Delayed Background Process and Result in jQuery?

I have a rather extensive PHP page that does a lot of IP address validation for our product licensing. One of those validation routines can take 20-30 seconds, while the bulk of them happen locally and so show up very quickly. I'd like to launch that longer one in a separate jQuery GET, and display it's results while they review the results of the faster ones.
Here's the pseudo-code for the "fastchecks" that I'm working from - how/where would a "slowchecks" be launched?
$.ajax(
{
type: "GET",
dataType: "json",
url: "license/fastchecks/" + $("#ipblocks").val(),
error:function (xhr, ajaxOptions, thrownError){
alert("IP Checking Error: " + xhr.status + ": " + thrownError);
},
success: function(fastresults)
{
/* Do stuff with my fast check results while I wait for my slow check results */
}
});
Is this possible? I keep going back to a timed event, but the process itself IS a delay, so that doesn't seem to make sense to me - am I missing something?
Your code is fine as is. You don't need to use any timers or anything like that. Your "slowchecks" would be exactly the same as your "fastchecks". The keyword here is Asynchronous. That success function doesn't get called until after the ajax call completes. So whatever you wanted to do with the data you get from your ajax call, put it in your success function, and that won't actually do anything until the results are returned.
Also, you would run both Ajax calls at the same time. Each one will run it's own success function when it completes.

Could AJAX results be out of synch and cause a discrepancy in polled results?

I am developing functionality similar to an auction, using jQuery, AJAX, PHP and mySQL.
Ajax accesses the server every second to get the most recent bid, and during this call we also get the remaining time from the server to keep all participants in sync.
I have two issues:
1) Occasionally the time remaining flickers back to the value of the previous time for a fraction of a second. Could this is to do with the asynchronous results getting out of sync?
Snippets of the relevant code:
function dotimer() {
updateScreen();
setTimeout('dotimer()',1000);
}
function updateScreen(){
$.ajax({
type : 'POST',
url : 'getinfo.php',
dataType : 'json',
data: { /* various params are passed to php */ },
success : function(data){
/* other info processed here...*/
$("#countdowntimer").html(data.secondsremaining);
},
error : function(XMLHttpRequest, textStatus, errorThrown) {}
});
}
getinfo.php:
$return['secondsremaining'] = strtotime($end_time)-strtotime("now");
/* get other infor from database... */
echo json_encode($return);
(setTimeout and setInterval both had the same results.)
2) Is accessing the database every second excessive? I can't see an alternative to ensure information is up-to-date. Is there a better way to do this?
The auction is for a relatively short period of time (30 min) and we do not expect any more than 10 participants.
Any advice/suggestions welcome, thanks!
I think that's exactly your problem. As the requests are asynchronous, you cannot control the order that they are executed. You have to synchronize your requests and avoid multiple requests ie you can only do a new request if there aren't pending requests, else you cannot control when the callback for each request is fired.

How to delay ajax query?

I read a lot of questions, but they doesn't working in my case.
My situation is: my ajax query to database to insert infromation. But in my web-application user can click on buttons very quick so previous ajax query is not finished, and there is where bugs are appear.
All i need to do is a delay between queries, so future queries will do only after previous is done.
Here is a code:
$('#save').click(function(){
var user_input=$('#user').val();
var section=$('#section').val();
$('#loading_info').append('<p><img src="Images/loading.gif" alt="loading" id="loading"/></p>');
$.ajax({
url: 'submit_db.php',
type: 'POST',
data: 'section='+section+'&user_input='+user_input,
success: function(result){
$('#response').remove();
$('#loading_info').append('<p id="response">' + result + '</p>');
$('#loading').fadeOut(500, function(){
$(this).remove();
});
}
});
return false;
});
What i tested and not working: insert timeout:3000 into ajax - 1 query is ok, but after this, the whole application freezes; set timeout using ajaxSetup() - the same situation. Tested setInterval function and put ajax query to it - but after it there were no ajax, application opened an implementing php file and freezes.
This not working:
$('#save').click(function(){
var t=setTimeout(function(){
var user_input=$('#user').val();
var section=$('#section').val();
$('#loading_info').append('<p><img src="Images/loading.gif" alt="loading" id="loading"/></p>');
$.ajax({
url: 'submit_db.php',
type: 'POST',
data: 'section='+section+'&user_input='+user_input,
success: function(result){
$('#response').remove();
$('#loading_info').append('<p id="response">' + result + '</p>');
$('#loading').fadeOut(500, function(){
$(this).remove();
});
}
});
return false;
},3000);
});
And this is not working too:
$('#save').click(function(){
var user_input=$('#user').val();
var section=$('#section').val();
$('#loading_info').append('<p><img src="Images/loading.gif" alt="loading" id="loading"/></p>');
$.ajax({
url: 'submit_db.php',
type: 'POST',
timeout: 3000,
data: 'section='+section+'&user_input='+user_input,
success: function(result){
$('#response').remove();
$('#loading_info').append('<p id="response">' + result + '</p>');
$('#loading').fadeOut(500, function(){
$(this).remove();
});
}
});
return false;
});
And finally this is not work too:
$.ajaxSetup({
timeout:3000,
});
Thanks in advance
What I suggest is to create a boolean and disable any button.
Create a boolean called "buttonPressed", this is set to false. When a submit is made, you check in your code if "buttonPressed" is set to false. If this isn't set to false, skit the AJAX request, otherwise set the buttonPressed to true and do the AJAX request. When the request is done, set the buttonPressed back to false and a new buttonpress will be allowed.
The problem is propably in that: user clicks 3 times in second, and afeter 3 seconds of timeouts, three quersies and sended in one second.
Use setTimeout, but clear this timeout everytime user clicks, so every time user clicks, timer is reseted, and you don't have to worry about query "queue".
Other solution is to detect does timer working, and ignore or queue user click (queue by creating new timet with value of 3000 + rest time of the actual timer
Paul Peelen's answer is probably the best one for you, but another safe solution would be to queue your requests. It will allow your code to execute asynchronously but still sequentially and even (potentially) allows you to kill duplicate requests before they even leave the machine. The way I've done this is something like this:
Create an array to hold your requests.
When the user's action causes a request, throw it into the end of the queue.
Immediately call a queue processor. If a previous requests hasn't resulted in a response yet, do nothing -- just leave it in the queue. Otherwise, remove the first item from the queue and process it. At this point, you could also look through the other queued requests and remove duplicates, or push high-priority requests to the top of the queue.
When the response is received, send it to wherever it needs to go and tell the queue processor to process the next request.
It's actually pretty simple to build, and I'm sure there are better variations out there. If server stability is a possible issue, you should build in some sort of process to kill dead requests (zombies).
Use a sentinel variable so that only one request can happen at a time. If it makes sense for the user to be able to have more than one request going then implement a queue for the requests, where the call to process the next element in the queue happens after the previous request has been handled.

AJAX Post Not Sending Data?

I can't for the life of me figure out why this is happening.
This is kind of a repost, so forgive me, but I have new data.
I am running a javascript log out function called logOut() that has make a jQuery ajax call to a php script...
function logOut(){
var data = new Object;
data.log_out = true;
$.ajax({
type: 'POST',
url: 'http://www.mydomain.com/functions.php',
data: data,
success: function() {
alert('done');
}
});
}
the php function it calls is here:
if(isset($_POST['log_out'])){
$query = "INSERT INTO `token_manager` (`ip_address`) VALUES('logOutSuccess')";
$connection->runQuery($query); // <-- my own database class...
// omitted code that clears session etc...
die();
}
Now, 18 hours out of the day this works, but for some reason, every once in a while, the POST data will not trigger my query. (this will last about an hour or so).
I figured out the post data is not being set by adding this at the end of my script...
$query = "INSERT INTO `token_manager` (`ip_address`) VALUES('POST FAIL')";
$connection->runQuery($query);
So, now I know for certain my log out function is being skipped because in my database is the following data:
alt text http://img535.imageshack.us/img535/2025/screenshot20100519at125h.png
if it were NOT being skipped, my data would show up like this:
alt text http://img25.imageshack.us/img25/8104/screenshot20100519at125.png
I know it is being skipped for two reasons, one the die() at the end of my first function, and two, if it were a success a "logOutSuccess" would be registered in the table.
Any thoughts? One friend says it's a janky hosting company (hostgator.com). I personally like them because they are cheap and I'm a fan of cpanel. But, if that's the case???
Thanks in advance.
-J
Ok, for those interested.
I removed the full URL http://www.mydomain.com/functions.php
and replaced it with the local path functions.php and that did the trick.
Apparently AJAX has issues with cross domain ajax calls and I'm not on a dedicated server, so I imagine what's happening is every couple hours (or minutes) I am somehow hitting my script from a different location causing AJAX to dismiss the POST data.
-J
Try enabling error reporting on the jquery $.ajax function, your code would look something like
function logOut(){
var data = new Object;
data.log_out = true;
$.ajax({
type: 'POST',
url: 'http://www.mydomain.com/functions.php',
data: data,
success: function() {
alert('done');
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus+" - "+errorThrown);
}
});
}
See if that sheds light on your situation.
I have a strong feeling that it's more of a server side issue rather than the client's.
The odd thing is that you see the problem for a period of time. If the client works at all, then at the minimum refreshing the page or restarting the browser should fix it.
The die() at the end of the function is suspicious, but I am not quite sure how it will affect it.
Btw you can see http headers in FireBug's Net tab, to know whether those parameters has been sent properly.

Categories