0

I have a page with 10 images that are hosted on amazon aws and for some reason the retrieval is very slow etc.

I am trying now to show a page without any images for thumbnails and then use AJAX call to get them. So since one particular image "fetching" cycle in the PHP script could take a really long time, I've created an Interval inside an example script that will eventually call a controller/method URL that will, in turn, retrieve the correct image for each thumb "slot", based on some other parameters, ID's of entities etc. ( a lot of stuff involved in this ).

I managed to do an AJAX call on every 2 seconds ( based on interval of course ), but I don't want to wait full 2 seconds to fetch another image in the set, if AJAX call completes in, for example, 0.5 seconds ( wasting 1.5 seconds of pure wait time there ).

So I am trying to figure out here how to, when jQuery ajax.done() is called, I could "break out" of this wait time of interval wait time cycle and make another AJAX call straight away. Tried doing it a couple of ways, but to vain.

HTML and JS:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="style.css"/>
</head>

<body>

<ul class="thumbs">
    <li><img src="images/no-image.jpg" alt="buffalo soldier"/></li>
    <li><img src="images/no-image.jpg" alt="buffalo soldier"/></li>
    <li><img src="images/no-image.jpg" alt="buffalo soldier"/></li>
    <li><img src="images/no-image.jpg" alt="buffalo soldier"/></li>
</ul>


<script src="https://code.jquery.com/jquery-2.2.1.min.js"></script>
<script>

$(document).ready(function() {


    var thumbsList = $('.thumbs'), // ul of images
        // append loader image to all images that need loading
        // ( if to be appended as loader image to images one by one, when ajax call is made, do this in the interval function instead )
        totalImagesToFetch = thumbsList.find('li img').attr('src', 'images/loader.gif').length, 
        currentPosition = 0;


        // kreiraj interval koji fetchuje sliku po sliku 
        var fetchThumbInterval = setInterval(function() {
            console.log('called');

            // dont call interval anymore if we fetched all the needed image thumbs
            if(currentPosition >= totalImagesToFetch - 1) clearInterval(fetchThumbInterval); 

            fetchMeNewThumb = $.ajax({
                url: "process.php",
                method: "POST"
            });

            fetchMeNewThumb.done(function(data) {
                console.log(currentPosition);
                thumbsList.find('li img:eq(' + currentPosition + ')').attr( "src", data ); // String: URL for image src attribute
                currentPosition++;
                resetInterval(fetchThumbInterval, 2000);
            });

        }, 2000);

        function resetInterval(intervalName, miliseconds) {
            clearInterval(intervalName);
            setInterval(intervalName, miliseconds);
        }



});

</script>

Simple CSS:

.thumbs li {
    display: block;
}

.thumbs li img{
    width: 400px;
    height: 400px;
}

And the images used are just some random images found online. P.S. ( it works correctly and calls AJAX every 2 seconds, if you comment out the call to resetInterval() function :)

  • 1
    As is often the case, `setInterval` can be a pain to handle. Why not simply `setTimeout`? One that waits for 2 seconds to do the next ajax request, and if the current one succeeds early, you simple clear that timeout and trigger the next request *manually*. No crazy fiddling with an interval. – Yoshi Mar 01 '16 at 12:45
  • Gonna try with that approach now, thank you for the suggestion :) – Novica Vukobratovic Mar 01 '16 at 12:50
  • Oh, compulsive downvoter on the loose. If you (not you OT) really think something is amiss enough to justify a downvote for all three people answering this question, you might as well just leave a comment. – Yoshi Mar 01 '16 at 13:02

2 Answers2

0

Look at Abort Ajax requests using jQuery.

What you actually want is to wait certain amount of time, if the request is not processed (e.g. sucess/error) in said time, .abort() it and start new timer with same request. Am I correct?

If so, check abort and change your code.

As suggested setTimeout is much better. Create function just for calling the ajax and if succeeded fill the thumb and call the function once egain. In setTimeout just clear the ajax calls and call said function egain.

I hope I was clear, if you need sample code, just let me know. But I suggest writing it by yourself.

Community
  • 1
  • 1
charlie
  • 69
  • 5
  • Thanks for the suggestion, however, I don't want to abort the ajax request, just keep it running and proceed to the next AJAX request which should start fetching the next image – Novica Vukobratovic Mar 01 '16 at 13:37
  • Ou, okay I understand your problem now, check this snippet: https://jsbin.com/canizaw/edit?js,console,output – charlie Mar 01 '16 at 14:17
  • This really looks like the way to go, but it seems that it has some serious bug in it :) Something with currentPosition. Because it is being incremented before the call to fetchImage() function, it messed up the logic. If I move it inside the fetchImage() functions $.ajax.done() call, it doesn't work either, returns position 0 every time. – Novica Vukobratovic Mar 01 '16 at 15:24
  • That's not a bug, that's actually needed. If you notice, there is recursion used for this, and you need condition to end the recursion. Let me change the function: http://jsbin.com/canizaw/edit?js,console,output You will see 1,2..5 because there is no ajax call. – charlie Mar 01 '16 at 16:04
  • I'll try figuring this out. Thanks a lot for your help ! :) – Novica Vukobratovic Mar 01 '16 at 16:19
-2

Update your AJAX to use success

$.ajax({
     url: "process.php",
     method: "POST",
success: function(data) {
//do whatever after ajax successfully completes.
}
 }); 
jonmrich
  • 4,233
  • 5
  • 42
  • 94
  • If I am not wrong, this is going to do basically the exact same thing :) Tried this approach after you've suggested it, but I still have to wait 2 seconds before making another ajax call since ajax call is inside interval function. And I don't want to "wait" for ajax to actually complete, since the action it is supposed to do could take a long time, I want to AT MOST wait for 2 seconds, then fire another AJAX call, but if previous AJAX call was done, I want to fire another AJAX call even before 2 seconds are up, if that makes sense :) – Novica Vukobratovic Mar 01 '16 at 12:34