I'm currently working on a script that loads content when either you trigger it (by clicking a link), or you scroll to the bottom of the page. I'm doing this for fun, but it is slowly turning into a nightmare... The triggered part works correctly, while the "scroll to the bottom" part sometimes works and sometimes doesn't. It will sometimes load a post twice, and sometimes repeat the sets of posts (I'm loading 5 at a time) and not display the next set, my guess is that it is because it loads content so fast, that:
- The queries get all mixed up (AJAX calls/mysql queries/Responses...?) or...
- There's some kind of problem with the DOM (I guess this is the correct way of calling this...) or...
- It is the cause of another glitch that I can't currently think of because of my basic knowledge...
The problem arises when you keep the scroll bar down, and so it loads the content very fast, it is especially a problem with Firefox, since if you are already at the bottom and refresh the page, it will load indefinitely until there are no more posts, and again, it does it really fast.
I've tried different approaches, all day... and I can't find a solution. First, I tried setting a flag, so that when each AJAX call finishes, it increases a certain variable by the number of posts loaded, and will only execute the call again if the number has been increased, and it must do so orderly (which in my head meant succesful AJAX call). This didn't work.
Then I tried setting a timeout, for the AJAX call, and then for the function that contains that call, and then for the function that executes the function in the first place (scrolling to the bottom), this kind of worked, but with the drawback of it not doing anything for that timeout (and thus, not even displaying the "loading" html) and with the situation happening fewer times, but still happening. I also tried setting the timeout in the $.ajax() function, which I think is a different kind of timeout, because it did not do what I desired...
Finally, I tried making async false, which I read is a bad thing, because it hangs the page until it's done, and because it is also deprecated; needless to say, it didn't work either (I didn't notice any visible change in behaviour).
I'm really lost here; I'm not even sure why this "glitch" happens...
Here's my code...
$.ajax({ //Removed some code in order to make it brief
url: 'load.php',
type: 'post',
dataType: 'json',
data: {offset: countContent, limit: displayNumber},
success: function(data)
{
if(data)
{
for(var i=0;i<display_n;i++)
{
var title = data[i][1];
var author = data[i][2];
var img = data[i][3];
var date = data[i][4];
var htmlStr =
'<div class="post" id="'+i+'"></div>';
$(element).append(htmlStr);
$(element).children('#'+i+':last').hide().fadeIn(200+(i*250));
}
}
else if(data == null){
//Do something when there are no more posts
}
},
error: function() {
// Error
}
});
And the php that processes the ajax call
<?php
$offset = (int) $_POST['offset'];
$limit = (int) $_POST['limit'];
$db = 'mysql:host=localhost;dbname=posts;charset=utf8';
$u = 'username';
$p = 'password';
$con = new PDO($db,$u,$p);
$q = $con->prepare("SELECT id, title, author, img, date FROM articles
ORDER BY id DESC LIMIT :limit OFFSET :offset");
$q->bindParam(':offset',$offset,PDO::PARAM_INT);
$q->bindParam(':limit',$limit,PDO::PARAM_INT);
$q->execute();
$articles = $q->fetchAll(PDO::FETCH_NUM);
$con = null;
$array_count = count($articles);
if ($articles){
for ($i=0;$i<$array_count;$i++)
{
$articles[$i][4] = date("d F Y",strtotime($articles[$i]['4']));
}
echo json_encode($articles);
}
else
{
$articles = null; //sends null if the data is empty
echo json_encode($articles);
}
?>
Is there any way to "delay" the ajax call before the other one gets executed, so that the articles load correctly? Or wait till everything in the ajax loaded as according to plan before going to the next one? What can I do in this case?
I'm sorry if this post is kind of huge, I guess I wanted to make a point, ha. Help is very much appreciated, thanks.
EDIT: Here's what I posted below, and the solution:
I set a global variable running to false, and wrapped the whole AJAX call inside an if !running condition, immediatly making the variable true after entering the loop, and making it false again on either the "complete: " parameter of the $.ajax function or via $.ajaxComplete(). I'm guessing one can also use .on() and .off() statements to bind and unbind the event trigger, but I found the previous method so much more simple.
This allows the AJAX call to finish before the other one starts, and the content is displayed correctly.