jquery php long polling request issue - php

I'm making a chat which is based on long polling (something like this )with PHP and jQuery. once whole page is downloaded in browser, a function makes a long polling request to the back-end with some timeout limit, when data comes from back-end it again makes the long-polling request and if any error, it will again make new long-polling request.
Problem : analyzing the traces by firebug, I've noticed that some times the long polling request is running 3 or 4 times, however it should not. there should only one long-polling request running per page.
however the code works perfectly. but long-polling request duplication is the issue.
function listen_for_message(){
// this functions is makes the long-polling request
$.ajax({
url: "listen.php",
timeout:5000,
success: function(data) {
$('#display').html(data);
listen_for_message();
}
error: function() {
setTimeOut("listen_for_message()",2000); // if error then call the function after 2 sec
}
});
return;
}

Try to terminate requests manualy:
var connection;
function longpoll() {
if(connection != undefined) {
connection.abort();
}
connection = $.ajax({
...
complete: function() {
longpool();
}
});
}
It may also be a Firefox/firebug issue (showing aborted connections as running), test it in Chrome.
UPDATE:
"In Firefox 3.0+ only, script and JSONP requests cannot be cancelled by a timeout; the script will run even if it arrives after the timeout period."
http://api.jquery.com/jQuery.ajax/

Related

Polling Apache server not responding

The apache server I am using to develop my system will not respond to request while the scripts that control the polling of messages is being run. This only happends on a domain level meaning that I can send an http request to any other apps hosted localy and get a response. When I do eventually get a response from this its about a minute later.
Here is the Js
window.fetch_messages = function ()
{
var last_message = $("div.message:last").attr('data-ai_id');
var last_message_status = $("p.message_status:last").text();
var project_id = getParameterByName('project-id');
$.ajax({
url:'/project_messages',
type:'POST',
data:{ project_id:project_id, latest_message:last_message, status:last_message_status },
timeout:50000,
async: true,
success:new_messages, // This upon completion also resends the request
error:function(data){ console.log(data); setTimeout(fetch_messages(),50000); }
});
}; // When On the page that uses this I call this function to start polling
Here is the server side code
do
{
// Check for status change
$status_change = $this->mentor_model->query_status($this->project_id, $this->last_message_id, $this->last_message_status, $_SESSION['user']);
// Check for new messages
$messages = $this->mentor_model->query_messages($this->project_id, $this->last_message_id);
// If there is a status update or new message.
if($messages || $status_change)
break;
usleep(1000000);
}
while(empty($messages) && empty($status_change));
echo json_encode(array("messages"=>$messages, "status"=>$status_change));
exit;
While this action is being run The server takes a long time to handle any request weather it be a GET, POST or another AJax request. Iv also tried changing both code sets to no avail as long as its long polling, the server will take a long time to handle.
Do I have this wrong or is there some apache setting I'm suppose to change. Using xamp on windows 8.1 also tried wamp with no change
Thanks to steven for this. Ansewer taken straight from the source of php manual page
for session_write_close();
You can have interesting fun debugging anything with sleep() in it if
you have a session still active. For example, a page that makes an
ajax request, where the ajax request polls a server-side event (and
may not return immediately).
If the ajax function doesn't do session_write_close(), then your outer
page will appear to hang, and opening other pages in new tabs will
also stall.

Ajax Call Hangs Browser - I don't care about the response

How do I abort an Ajax call if I don't really care for the response as I don't want to hang the browser?
The situation is I have an ajax call that could trigger the server sending over a 1000 emails in some cases. 99% of the time it is only a few or tens of emails.
So with the 1000 email ajax call, the browser waits sometimes 5 minutes before it gets the success message, thus the user has to wait.
I have tried setting a timeout, but this still hangs. I'd like to wait about 20 seconds and then abort waiting for the response.
var request = jQuery.ajax({
type: "post",url: "admin-ajax.php",
data: {
action: 'send_email',
emailHTMLMessage: tinyMCE.activeEditor.getContent(),
_ajax_nonce: '<?php echo $nonce; ?>'
},
timeout: 20000, //Set your timeout value
success: function(html){ //so, if data is retrieved, store it in html
window.scrollTo(0,0);
sendResults(html);
},
error: function(jqXHR, textStatus, errorThrown) {
if(textStatus==="timeout") {
<... I'd redirect to another html page here....>
} else {
alert("Another error was returned"); //Handle other error type
}
}
}); //close jQuery.ajax
I have tried request.abort() but this kills it immediately and the server never gets the send_email message.
How can I quietly ignore the response after 20secs while the server carries on doing it's thing?
In this post there are afew ways to keet the script running after the http request ends:
Can a PHP script start another PHP script and exit?
So you can leave your email script running on the server.
If you want to know the status you could make your email script update to a mysql table how many emails are sent and check with an ajax request the count from the mysql table.
If you're sending 1000 emails, that call is going to contain some overhead no matter what you do. You are also going to have to wait until all the information is sent to the server before you want to allow the user to leave the page as well.
My suggestion would be to change the server code to respond as soon as the server gets their request. That way the client isn't waiting on the server to finish sending the entire batch, rather just waiting for their request to be received by the server.
Just post without using the success, timeout or error callbacks.
You might want to try creating a new get request for each email:
for(i = 0; i<1000; i++){
var request = $.ajax({
type: "post",
url: "admin-ajax.php",
data: {'i':'nada'}
});
};
In this case, I used a for loop, but you could also use an array of emails:
var emails = new Array(1000);
$.each(emails, function(){
var request = $.ajax({
type: "post",
url : "admin-ajax.php",
data: {'i':'nada'}
});
});

jQuery ajax call never finishes (success and error callbacks are not fired)

I've an ajax request to the server and I only need to know when it finishes to redirect the user to a second page. It is working most of the times but if the server takes too long to answer (e.g. 10 min) then it can happen that no callback function is called and the request keeps waiting.
My code is as follows:
$.ajax({
type: 'post',
url: 'request.php',
success: function(data) {
alert("Success: "+data);
window.location.replace("success.php");
},
error: function (xhr, ajaxOptions, thrownError) {
alert("Ajax error: "+xhr.status+" - "+thrownError);
window.location.replace("error.php");
}
});
As you can see, I've tried to check if there is any error but as far as I have arrived, the ajax request behaves as if it had not finished (no alert or redirection is fired). However, the PHP code in the server runs without errors until the end.
I have no idea where to search for the error because I was thinking about a timeout problem both in the browser or in the server but it seems not to be the cause. And as the same code is working in short waiting times I cannot imagine other possible reasons.
Thank you!
I would bet on a timeout on your web server which invalidates the connection, this might mean that no answer is sent back.
In that case, the ajax timeout option might be good for you.
Having said that, if I were you, I would do this differently: since you're already using ajax, why not ping the server every x seconds and check if the process has finished and it's time to redirect, instead of keeping the connection open? This way you don't have timeout issues, and you don't hold the connection captive over a session which doesn't send any data and only waits for a server side process to finish. More scalable and robust, and more appropriate for http connections.

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

Long polling timeout issue

I'm doing a long poll method chatroom. But it seems that, when a long poll occurs and I refresh the page in chrome OR i try to send another async request everything times out (i.e i cant load my domain again until i close/reopen the browser).
My client side code is:
$(document).ready(function() {
setTimeout(
function () {
longPollForMessages();
},
500
);
});
function longPollForMessages()
{
$.ajax({
url: url,
dataType: 'json',
success: function(data) {
$('#chat_messages').append('<div>'+data.messages+'</div>');
longPollForMessages();
}
});
}
And my serverside:
while(true) {
$messages = $db->getMessages();
if (!$messages || sizeof($messages)==0) {
sleep(1);
} else {
echo '{"message":'.json_encode($messages).'}';
die();
}
}
Any ideas? Assume no syntax errors.
I can see you have already answered your own question, but I recently had a similar problem and found another way to handle it is to disable the setTimeout on ajax call, then restart it on success. That way you aren't pinging your server for information when it isn't ready to give it.
I figured it out from this question: stackoverflow.com/questions/4457178/… - php locks a given session until the page is done loading so the second ajax call wasn't able to go through. You have to release the lock by calling session_write_close();

Categories