views:

155

answers:

2

Hello,

I have an issue with javascript/jQuery...I have a web service that will process information from a list from the client. What I want to do is have the client send the data piece by piece allowing the web service to do its job without being overloaded. Also I am using a jQuery UI progressbar which will allow the user to see the progress of their request.

My problem is that I am using a for loop and when the loop runs it seems that the loop runs to completion so if there are 10 pieces of data to process, all ten runs simultaneously...

What I'm asking is there a way to make the for loop pause until a success message is received from the server?

This is what I tried:

var nums = [1,2,3,4,5,6,7,8,9,10];

        for (var i in nums) {

        //I also tried 
        //for (num = 1; num <= 9; num++) {

            //start loop
            $("#progressbar").progressbar('option', 'value', num);
            var input = {
                "num": num,
                "total": 100
            }

            //  .progressbar('option', 'value', 37);              
            var jsonStr = JSON.stringify(input);
            //d = '{' + d + '}';
            $.ajax({
                type: "POST",
                url: "AjaxWcf.svc/TestModal",
                contentType: "application/json; charset=utf-8",
                data: jsonStr,
                dataType: "json",
                success: function(msg) {
                    $("#progressbar").progressbar({
                        value: num
                    });

                    //alert(msg.d);
                    //                    jQuery('#modalContentTest.loading').fadeOut(200);
                    //                    setTimeout('jQuery.modal.close()', 1000);

                    $("#message").value = msg;
                },
                error: AjaxFailed
            });
        }

        function AjaxFailed(result) {
            alert(result.status + ' ' + result.statusText);
        }
    });

I know its late so maybe I'm crosseyed and maybe some sleep will help me see this from a different angle, buuuuuttt if someone could help with this or show me an alternetive, I'd appreciate it.

Thanks!!!

+1  A: 

You'll want to recurse from your callbacks so that it calls the next in the sequence (if it exists).

var processArrayAsync = function(array) {
    // Define the iteration handler as a static property to avoid the 
    // overhead of its creation for mulitple calls to processArrayAsync.
    // If you'll only be using this method once or twice, then this 
    // technique isn't necessary
    if ( !processArrayAsync.step ) {
        processArrayAsync.step = function(i) {
            if ( !array[i] ) { return; }

            $("#progressbar").progressbar('option', 'value', array[i]);                
            $.ajax({
                type: "POST",
                url: "AjaxWcf.svc/TestModal",
                contentType: "application/json; charset=utf-8",
                data: {
                    "num":   array[i],
                    "total": 100
                },
                dataType: "json",
                success: function(msg) {
                    $("#progressbar").progressbar({value: array[i]});
                    $("#message").value = msg;                            
                    // After the callback has completed, process the next 
                    // element in the array
                    processArrayAsync.step(i+1);
                },
                error: function(msg) {
                    AjaxFailed(msg);
                    // You may want to stop processing if one request 
                    // fails, if so, just change this back to 
                    // `error: AjaxFailed`
                    processArrayAsync.step(i+1);
                }
            });
        };
    }

    processArrayAsync.step(0);
};

var nums = [1,2,3,4,5,6,7,8,9,10];
processArrayAsync(nums);
Justin Johnson
Thank you...I like both examples, but I wouldn't want the process to stop if one request fails, so this one suits me a little better.
wali
You're welcome mate
Justin Johnson
+5  A: 

Your problem is that AJAX calls are asynchronous, meaning that the line $.ajax(...) will return right away without waiting for the server to receive the request and send a response.

While it is possible to send a synchronous request, you should never do it, because it will completely freeze the browser until the request is finished. (Javascript always runs on the browser's UI thread)

You need to send each request in the success callback from the previous request.

For example:

function sendPart(num) {
        $("#progressbar").progressbar('option', 'value', num);
        var input = {
            num: num,
            total: 100
        };

        var jsonStr = JSON.stringify(input);

        $.ajax({
            type: "POST",
            url: "AjaxWcf.svc/TestModal",
            contentType: "application/json; charset=utf-8",
            data: jsonStr,
            dataType: "json",
            success: function(msg) {
                $("#message").value = msg;

                if (num < 10)
                    sendPart(num + 1);
            },
            error: AjaxFailed
        });
    }
}

sendPart(1);

Note that this will not send the next request if the previous one failed.

SLaks
+1 nice answer SLaks.
karim79
I like your answer because it is simple enough for me to fully understand, I hope you understand I selected Justin's answer because it was a little more suited for what I ultimately need...
wali