0

i have already posted a similar question here, but failed to get a response that will fix my problem, also the problem has changed a bit so i'm re-posting and desperate to get some help!

link to previous question:

ajax long polling with mysql

CURRENT CODE:

JS(I run it from php):

$oldIDq = mysql_query("SELECT * FROM messages ORDER BY id DESC LIMIT 1");
while($oldrow = mysql_fetch_array($oldIDq)){
$oldID = $oldrow['id'];    
}

$func = '
var oldID = '.$oldID.';

function wait() {
$.ajax({
    type: "GET",
    url: "../scripts/msg_scripts/msg.php?oldid=" + oldID,
    async: true,
    cache: false,

    success: function (data){

        if(data != \'1\'){
            var json = eval(\'(\' + data + \')\');
             if (json[\'msg_content\'] != "") {
                  alert("new meassage added"); 
                  } 
                  oldID = json[\'oldID\']; 
                  setTimeout(\'wait()\',1000); }

    },

    disconnect: function()
    {
        return false;
        setTimeout(\'wait()\',1000);
    },

    error: function(XMLHttpRequest, textStatus, errorThrown){
      alert("error: " + textStatus + "(" + errorThrown + ")");  
      setTimeout(\'wait()\',1000);
    }

});
}

$(document).ready(function(){

    wait();
});
';

SERVER:

    $connect = mysql_connect ("localhost", "root", "")

or die ("couldnt connect");
mysql_select_db ("***") or die ("not found"); //if db was not found die
mysql_query("SET NAMES 'utf8'");

$oldID = $_GET['oldid']; 

if($oldID == "") {

die('timeout');
}
else{

$result = mysql_query("SELECT id FROM messages ORDER BY id DESC LIMIT 1");
while($row = mysql_fetch_array($result))
{
    $last_msg_id = $row['id']; 
}
while($last_msg_id <= $oldID)
{
    usleep(10000);
    clearstatcache();
    $result = mysql_query("SELECT id FROM messages ORDER BY id DESC LIMIT 1");
    while($row = mysql_fetch_array($result))
    {
        $last_msg_id = $row['id'];
    }
}



$response = array();
$response['msg_content'] = 'new';
$response['oldID'] = $last_msg_id;
echo json_encode($response);
}

now, i had a session running on the server side of the process and i removed it for now because i understood that long polling has a problem with sessions i also have sessions running on the page which sends the ajax request, since i removed the session my problem has improved in a way, what happens now is that i can basically click on a link on my website and exit the page and get an error, but if i do it more than 4-5 times, the browser freezes an every click on any link just reruns the ajax function and i get a different error. if i refresh the page of the request i imidetly get the second error and the browser freezes. also if that's helpful information if i close the browser and try to reopen any page of my site it doesn't load at all unless i rerun my server(working on localhost right now) also tried it with chrome and ff.

can some one please point me towards the solution?

Community
  • 1
  • 1
durian
  • 510
  • 1
  • 7
  • 24
  • It does not have a problem with "sessions" if you just close the writing to the session with [session_write_close](http://php.net/manual/en/function.session-write-close.php) – dbf Sep 12 '12 at 15:52
  • i did it already but it had no effect – durian Sep 12 '12 at 15:56
  • sorry to say, but then you did it wrong – dbf Sep 12 '12 at 15:57
  • Ok, so every time you click a link, do you send a new request with the exact same source `../scripts/msg_scripts/msg.php?oldid=15`, if oldID were to have the value 15? – dbf Sep 12 '12 at 16:02
  • ok then: session_start(); $var_id = $_SESSION['id']; $var_fn = $_SESSION['firstname']; $var_ln = $_SESSION['lastname']; $var_mail = $_SESSION['email']; if (!loggedin()){header ("Location: index.php");} if ($_GET['id']) {$id = mysql_real_escape_string($_GET['id']);} else if (isset($_SESSION['id'])) {$id = mysql_real_escape_string($_SESSION['id']);} session_write_close(); - this is how i close it. – durian Sep 12 '12 at 16:02
  • if i look in firebug it shows the same one, yes. – durian Sep 12 '12 at 16:05
  • But if you click the link ones, and wait for the response to return, it works correctly? – dbf Sep 12 '12 at 16:22
  • when the links still work what i get is: prompt aborted by user [Break On This Error] throw Components.Exception("prompt aborted by user", Cr.NS_ERROR_NOT_AVAILABLE) nsPrompter.js (line 462) ,,,, but as it crashed and gets stuck and so on as i click on any link or refresh i get: the request with a red x near it and i get the same oldid... – durian Sep 12 '12 at 16:29
  • Hmm, have you tried a different browser? – dbf Sep 12 '12 at 16:33
  • chrome and FF, by the way as soon as it gets stuck in FF the website becomes also unavailible in chrome – durian Sep 12 '12 at 16:35
  • K, add just after ` – dbf Sep 12 '12 at 16:37
  • on the page that gets the request? – durian Sep 12 '12 at 16:42
  • See my updated answer with the code below – dbf Sep 12 '12 at 16:47
  • yes if i write exit then everything works fine but the request fails, so if it IS doing an endless loop how can i make it not too, and why is it doest it let me click links a couple of times before it starts doing it? – durian Sep 12 '12 at 16:53
  • Ok, have you also tried the code below on my updated answer? With the new `while` loop where I add a counter? And another thing, I don't know what you mean by _the request fails_, post the error or explain **what** fails and **why** it fails. Let me just say that you should avoid any loop being endless for various reasons. – dbf Sep 12 '12 at 16:57
  • it counted 101, sorry, it didnt fail ignore that – durian Sep 12 '12 at 17:10

1 Answers1

1

-- Updated again to retrieve all new messages

Reading your code, you only wish to return the last message, if so then the while loops are in this case pretty useless. Do keep in mind that there might be more 'new' messages between the oldID and the last ID inserted into your database which you skip, so does this code I provide

$connect = mysql_connect ("localhost", "root", "")
or die ("couldnt connect");
mysql_select_db ("***") or die ("not found"); //if db was not found die
mysql_query("SET NAMES 'utf8'");

$oldID = trim($_GET['oldid']);

// empty response, you may fill it with a default msg
$response = array(
  'msg_content' => 'none',
  'oldID' => $oldID
);

// this if statement will prevent to return a valid 
// JSON string to the ajax request
if(empty($oldID)) {
 die('timeout');
}
else {
  $result = mysql_query("SELECT id FROM messages WHERE id > ".addslashes($oldID)." ORDER BY id DESC");
  $index = 1;
  // check if results have new messages
  if(($num_rows = mysql_num_rows($result) > 0) {
    $response['msg_content'] = 'new';
    while($row = mysql_fetch_array($result)) {
      $response['new_msgs'][] = $row['id']
      if($index == $num_rows)
        $response['oldID'] = $row['id']; // set oldID to last record
  }
}
echo json_encode($response);  

--

To your comment on how to use session_write_close properly.

session_start(); 
  $var_id = $_SESSION['id']; 
  $var_fn = $_SESSION['firstname']; 
  $var_ln = $_SESSION['lastname']; 
  $var_mail = $_SESSION['email']; 
// close write to session here to release it for other sources 
session_write_close();

if (!loggedin()){
  header ("Location: index.php");} 
  if ($_GET['id']) {
    $id = mysql_real_escape_string($_GET['id']);} 
  // you are using session here, use the localized $var_id
  else if (isset($var_id)) {
    $id = mysql_real_escape_string($var_id);
}

When session_start() is called, the session at that point is locked for writing to any other source, except the current scope (.php file of execution) it's in. This is to make sure that no values can be changed during the readout of session values.

From the documentation

Session data is usually stored after your script terminated without the need to call session_write_close(), but as session data is locked to prevent concurrent writes only one script may operate on a session at any time. When using framesets together with sessions you will experience the frames loading one by one due to this locking. You can reduce the time needed to load all the frames by ending the session as soon as all changes to session variables are done.

To the getting stuck problem, I think the while loop is endless, request the page from your browser http://example.com/pathto/scripts/msg_scripts/msg.php and see what happens

$counter = 0;
while($last_msg_id <= $oldID)
{
    usleep(10); // changing to be a bit faster
    clearstatcache();
    $result = mysql_query("SELECT id FROM messages ORDER BY id DESC LIMIT 1");
    $row = mysql_fetch_array($result);
    $last_msg_id = $row['id'];
    $counter++;

    if($counter > 100)
      break;
}
echo "counted: {$counter}";
exit();
dbf
  • 3,278
  • 1
  • 24
  • 34
  • i did it...but what it does is just alert "new message" every second over and over again, while i want to get a response only when a new message is inserted into the db, and also i do need the while loop as later i would extract all the messages content from the db. – durian Sep 12 '12 at 17:56
  • Change `if (json[\'msg_content\'] != "")` into `if (json[\'msg_content\'] == "new")` – dbf Sep 12 '12 at 18:04
  • That works Perfectly! Thank you very very much! i also learned a lot :)) if i may, one final question...in fibug i can now see that the request is running every second should it show it like that rather than a loading one? – durian Sep 12 '12 at 18:19
  • Every second you execute a new request which should read in firebug as a new entry, that is what your javascript code does, so yes correct. – dbf Sep 12 '12 at 18:45
  • but shouldn't the long polling concept execute the function only when a new eatery was actually added to the db and then restart rather then start over every second(because this is what i was intending to do), which makes it look a little as if i was putting set Interval on it? or am i misunderstanding something? – durian Sep 12 '12 at 19:24
  • Your wait() function is recursive, meaning the setTimeout will be called every time wait() is executed (unless `data == 1`). Please look up the documentations and/or turorials of recursive functions, setTimeout and setInterval to resolve what you really want. – dbf Sep 12 '12 at 19:36