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();
Related
I'm trying to develop an application in which it is very important to detect changes in a database in real time. I have devised a method to detect the changes now by running an ajax function and refreshing the page every 3 seconds, but this is not very efficient at all, and on high stress levels it dosen't seem like an effective solution.
Is there any way I can detect if some change has been made in the database instantly without having to refresh the page? The sample code is attached. I'm using php as my server side language, with html/css as the front end.
$(document).ready(function() {
$('#div-unassigned-request-list').load("atc_unassigned_request_list.php");
$('#div-driver-list').load("atc_driver_list.php");
$('#div-assigned-request-list').load("atc_assigned_request_list.php");
$('#div-live-trip-list').load("atc_live_trip_list.php");
setInterval(function() {
$.ajax({url:"../methods/method_get_current_time.php",success:function(result){
$("#time").html(result);
}});
}, 1000)
setInterval( function() {
$.ajax({url:"atc_unassigned_request_list.php",success:function(result){
$("#div-unassigned-request-list").html(result);
}});
$.ajax({url:"atc_driver_list.php",success:function(result){
$("#div-driver-list").html(result);
}});
$.ajax({url:"atc_assigned_request_list.php",success:function(result){
$("#div-assigned-request-list").html(result);
}});
} ,2000);
});
Please help!
For me, the best solution is
On the server side write a service that identify the changes
On the client, check this service with websockets preferencially (or ajax if you can not use websockets), then if there have changes, download it, This way you have, economy and velocity with more funcionality
Examples Updated
Using ajax
function downloadUpdates(){
setTimeout(function(){
$.ajax({
url: 'have-changes.php'
success:function(response){
if(response == 'yes'){
// ok, let`s download the changes
...
// after download updates let`s start new updates check (after success ajax method of the update code)
downloadUpdates();
}else{
downloadUpdates();
}
}
});
}, 3000);
}
downloadUpdates();
Using websockets
var exampleSocket = new WebSocket("ws://www.example.com/changesServer");
exampleSocket.onmessage = function(event) {
if(event.data != "no"){
// ok here are the changes
$("body").html(event.data);
}
}
exampleSocket.onopen = function (event) {
// testing it
setInterval(function(){
exampleSocket.send("have changes?");
}, 3000)
}
Here (I have tested it ) and Here some examples of how to use websocokets on php, the problem is you will need to have shell access
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
}
});
}
$("#profile_bar").mouseover(function(){
<?php $_SESSION['sessionasdf'] = 'asdf'; ?>
});
Hello! I have been busy with this for an hour, but I'm deadbrain now. Can someone help me out or give me a hint? Is the function I wrote above, even possible?
Thanks in advance!
You need an Ajax Request to do this. You can't simply start a session in a script that's already been loaded.
$("#profile_bar").mouseover(function() {
$.ajax({
url: "sessionStartPage.php",
cache: false,
success: function(data) {
alert("session has begun. Refreshing page now");
location.reload(); //reload the page to load session variables
}
});
});
As I said you have to use a technique called AJAX..
So its time to start learning:)
http://www.smashingmagazine.com/2008/10/16/50-excellent-ajax-tutorials/
PHP run on server, JQuery(the javascript) run on browser.That's different.
And you can start the session at every page on server, rather than by the event on browser.
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/
I have a single page that I need to on occasion asynchronously check the server to see if the status of the page is current (basically, Live or Offline). You will see I have a function with a var live that is set when the page initially loads. I then do an ajax request to the server to retrieve whether the status of live is true or false. I compare the initial live variable with the newly returned data json object. If they're the same I do nothing, but if there different I apply some css classes. I recursively run it with setTimeout (Is there a better way to recursively do this?).
My Problem:
data.live doesn't change from it's initial time it runs even when it has changed in the db. I know my mysql is working because it returs the right value on the initial load. It seems like a caching issue.
Any help is greatly appreciated.
function checkLive() {
var live = <?=$result["live"]?>;
$.ajax({
type: 'get',
url: '/live/live.php',
dataType: 'json',
success: function(data) {
console.log('checking for updates... current:' + data.live);
if (data.live == live) {
return;
} else {
var elems = $('div.player_meta, object, h3.offline_message');
if (data.live == '1') {
elems.removeClass('offline').addClass('live');
} else {
elems.addClass('live').addClass('offline');
}
}
}
});
setTimeout(function() { checkLive() } ,15000);
}
checkLive();
Use the cache option of $.ajax() to append a cache breaker to the URL, like this:
$.ajax({
type: 'get',
url: '/live/live.php',
dataType: 'json',
cache: false,
//success, etc.
});
If that doesn't resolve it...look at firebug, see if a request is being made (it should be after this for sure), if it's still getting an old value, the issue is in PHP, not JavaScript.
Unrelated to the issue, just a side tip: If you need no parameters, you can skip the anonymous function call, this:
setTimeout(function() { checkLive() } ,15000);
can just be:
setTimeout(checkLive, 15000);
You can check if it's a caching issue by adding unique ID to the url:
change url: '/live/live.php', to url: '/live/live.php?'+new Date().getTime(),
Cheers
G.
I think Nick Craver has the right response.
For the other point of the question which is you SetTimeout , you could use SetInterval() and avoid the recursive call. But in fact I would stay with a setTimeout() and add a factor on the 15000 time. set that factor as a parameter of checklive. Then you will have a check which will be delayed progressively in time. This will avoid a LOT of HTTp requests from the guy which his still on your page since 48 hours.
Chances are that most of the time users will check for new pages in a regular manner, but someone staying for a very long time on a page is maybe not really there. Here's a piece of code I had doing that stuff.
function checkLive(settings) {
(...) //HERE ajax STUFF
setTimeout(function() {
if ( (settings.reload <2000000000) && (settings.growingfactor > 1) ) {
checkLive(settings);
settings = jQuery.extend(settings,{reload:parseInt(settings.reload*settings.growingfactor,10)});
}
},settings.reload);
}