0

Trying to do a while loop using $.getJSON to return progress of a certain task. The initial $.getJSON works flawlessly; however the loop never completes. I am passing certain variables through a backend php file which is the reason for the variables in the script.

$.getJSON('http://anyorigin.com/get?url=https://".$domain.".instructure.com/api/v1/courses/".$course_id."/course_copy/".$id."?access_token=".$token."&callback=?', function(data){
    var progress = data.contents.progress;
    alert(progress);
    var elem = document.getElementById('".$id."');
    elem.style.width = progress + '%';
});

var progress_check = 0;
//The part below doesn't work! //
do {
    $.getJSON('http://anyorigin.com/get?url=https://".$domain.".instructure.com/api/v1/courses/".$course_id."/course_copy/".$id."?access_token=".$token."&callback=?', function(data){
        var progress_check = data.contents.progress;
        alert(progress_check);
        var elem = document.getElementById('".$id."');
        elem.style.width = progress_check + '%';
    });
} 
while (progress_check < 100);

I want the script to update a specific div with a new css style to display the loading bar properly. Here is the div:

<div id='".$id."-div' class='progress progress-striped active'>
   <div id=".$id." class='bar' style='width: 1%'></div>
</div>

Not certain what i am doing wrong. Thanks in advance.

Niels Keurentjes
  • 41,402
  • 9
  • 98
  • 136
  • 1
    Indenting your code consistently and clearly will help you **dramatically** when reading your code. And make it a **lot** easier for people trying to help you to read it, too. Due respect, that code is *extremely* hard to read. (I was trying to clean it up for you, but http://jsbeautifier.org seems to be down...) – T.J. Crowder May 16 '13 at 17:32
  • I don't even see an infinite loop in your code. You're trying to do something in a loop that you should be doing with `setTimeout` anyway - JS is asynchronous, not multithreaded. Also, I'll add the [tag:jquery] tag on your post, not all Javascript is jQuery and you should specify it. – Niels Keurentjes May 16 '13 at 17:34
  • That's a horrible way of testing the progress. It may fire off thousands of ajax requests before the complete one happens, if the browser doesn't stop you before that. And it ruins the asynchronous nature of ajax. You also are not updating the variable on the outside of the ajax (which is why your loop is infinite) – Kevin B May 16 '13 at 17:38
  • possible duplicate of [How to return the response from an AJAX call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call) – user229044 May 16 '13 at 17:39
  • @meagar not really a duplicate - the devil is in the detail and a good solution for this won't necessarily require the same answer as to that question. – Alnitak May 16 '13 at 17:55
  • @Alnitak The root cause is the same, and I think essentially every question that misses the "AJAX is asynchronous" problem should be closed as a duplicate of the linked question as a matter of course. – user229044 May 16 '13 at 18:21
  • @meagar read my answer and see if you still agree. – Alnitak May 16 '13 at 18:31

3 Answers3

3

your var progress_check = data.contents.progress; is local variable it becomes zero each time function completes. change it to progress_check = data.contents.progress; and check.

Arpit
  • 12,767
  • 3
  • 27
  • 40
1

The $.getJSON call is asynchronous - the result isn't known until the AJAX call completes. Furthermore, because the function returns immediately it'll fire as many AJAX calls in parallel as it possibly can. On top of that, your progress variable is being overwritten inside the callback function, so the variable of the same name in the while condition is never updated.

Try this, instead:

function poll(url) {

    var def = $.Deferred();

    (function loop() {
        $.getJSON(url).done(function(data) {
            var progress = data.contents.progress;
            if (progress < 100) {
                def.notify(progress);
                loop();
            } else {
                def.resolve();
            }
        }).fail(def.reject);
    )();

    return def.promise();
}

which abstracts your polling into a function that returns a "promise".

You can then watch for progress events on that promise, and watch for completion of the loop:

poll(myUrl).progress(function(percent) {
    var elem = document.getElementById(...);
    elem.style.width = percent + '%';
}).done(function() {
    // this is called when the loop is finished
}).fail(function() {
    // this is called if any of the AJAX calls break the loop
});

and now your progress display logic is completely separated from the AJAX code, with the only hard-coded dependency in the poll function being which JSON property to look in to find the current progress value.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
0

use javascript timer to make ajax request, make progress track request in every 30seconds/60 seconds
This will be better than do while loop

Krishnarag
  • 56
  • 5
  • As mentioned in several of the OP comments, the setTimeout was the best way to handle this. after changing it and cleaning it up, it was quite simple. – user2390847 May 16 '13 at 21:49