Aaron Turecki
Aaron Turecki

Reputation: 355

jQuery.ajax - possible to fire two success callbacks per ajax request?

I'm trying to display two progress bars for multiple ajax requests. One progress bar reaches 100% each time one of my 18 ajax requests is complete and another reaches 100% when all 18 requests are complete. The first bar works great and is implemented in my ajax success callback. I'm having trouble triggering my second bar because it seems I need a second success callback...

Here is the code for my first ajax requests. It gets called 18 times because that is how many items are in my Config object.

for (var propt in Config) {

    var db = '...';
    var user = '...';
    var pword = '...';
    var func = '...';
    var dat = {"...": propt };
    var url = "https://...";

    var callData = jQuery.extend({"Db": db, "User": user, "Password": pword, "Function": func}, dat);

    $.ajax({
        type: "POST",
        url: url,
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(callData),
        xhr: function() {
            var xhr = new window.XMLHttpRequest();
            //Download progress
            xhr.addEventListener("progress", function(event){
                    var percentComplete = (event.loaded / event.total)*100;
                    //Do something with download progress
                            tableProgressBar(percentComplete);
            }, false);
            return xhr;
        },
        success: successHandlerRunTest1,
        error: errorHandlerRunTest1,
        dataType: "json"
    });
    $('#jsonMsg1').html('Running...');
    $('#jsonRslt1').html(' ');
}

I would also like to fire this success function simultaneously.

success : function (serverResponse) {
    response[response.length] = serverResponse;
    $('#progress-bar').text(current + ' of ' + total + ' tables are done');
    current++;
},

Unfortunately I don't believe I can call the second success function from within the first success function because the first receives special parameters containing JSON data.

I've tried something like...

success : function (serverResponse) {
    response[response.length] = serverResponse;
    $('#progress-bar').text(current + ' of ' + total + ' tables are done');
    current++;

    successHandlerRunTest1(data);
},

...but this doesn't work because the "data" object that my successHandlerRunTest1(data) receives is empty.

Is there a way to perform two success callbacks per ajax request?

Upvotes: 4

Views: 5062

Answers (3)

guest271314
guest271314

Reputation: 1

Try (this pattern) , utilizing deferred.always()

html

<progress id="p1" max="1" value="0"></progress>
<progress id="p2" max="17" value="0"></progress>
<span id="jsonMsg1"></span>
<span id="progress-bar"></span>

js

$(function () {
    var count = null;
    var Config = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17];
    for (var propt in Config) {

        var db = '...';
        var user = '...';
        var pword = '...';
        var func = '...';
        var dat = {
            "...": propt
        };
        var url = "/echo/json/";

        var callData = jQuery.extend({
            "Db": db,
            "User": user,
            "Password": pword,
            "Function": func
        }, dat);
        var successHandlerRunTest1 = function (data, textStatus, jqxhr) {
            // Do something with download progress
            $("#p1").val(1);
        };
        var response = [];
        $.ajax({
            type: "POST",
            url: url,
            contentType: "application/json; charset=utf-8",
            data: {
                json: JSON.stringify(callData)
            },
            beforeSend: function (jqxhr, setiings) {
                jqxhr.count = ++count;
                // Do something with download progress
                $("#p1").val(0);
            },
            /*
        xhr: function() {
            var xhr = new window.XMLHttpRequest();
            //Download progress
            xhr.addEventListener("progress", function(event){
                    var percentComplete = (event.loaded / event.total)*100;
                    //Do something with download progress
                            tableProgressBar(percentComplete);
            }, false);
            return xhr;
        },
        */
            success: successHandlerRunTest1,
            error: function (jqxhr, textStatus, errorThrown) {
                console.log(errorThrown)
            },
            dataType: "json"
        })
            .always(function (data, textStatus, jqxhr) {

            $('#jsonMsg1').html('Running...');
            response[response.length] = data;
            $("#progress-bar")
                .text(Number(data["..."]) 
                + ' of ' 
                + Config.length + ' tables are done');
            $("#p2").val(Number(data["..."]));
            // Do something with download progress
            if (data["..."] === "17" && jqxhr.count === 18) {

                console.log(data["..."]);
                $('#jsonMsg1').html('Done...');
                $("#progress-bar")
                    .text(Number(data["..."]) + 1 
                    + ' of ' 
                    + Config.length + ' tables are done');

            };
        });
        // $('#jsonRslt1').html(' ');
    };
});

jsfiddle http://jsfiddle.net/guest271314/z6DzF/4/

See

http://api.jquery.com/jQuery.ajax/#jqXHR

http://api.jquery.com/deferred.always/

Upvotes: 1

Bergi
Bergi

Reputation: 664920

Don't use the success parameter.

Use the done method to attach callbacks, as it returns the promise for chaining you can call it multiple times:

$.ajax({
    type: "POST",
    url: url,
    contentType: "application/json; charset=utf-8",
    data: JSON.stringify(callData),
    xhr: function() {
        var xhr = new window.XMLHttpRequest();
        xhr.addEventListener("progress", function(event){
            var percentComplete = (event.loaded / event.total)*100;
            tableProgressBar(percentComplete);
        }, false);
        return xhr;
    },
    dataType: "json"
})
.done(successHandlerRunTest1)
.fail(errorHandlerRunTest1)
.done(function (serverResponse) {
    response[response.length] = serverResponse;
    $('#progress-bar').text(current + ' of ' + total + ' tables are done');
    current++;
});

Upvotes: 7

Kyle Needham
Kyle Needham

Reputation: 3389

You could simply pass both callbacks inside the original success callback. Then use .apply to pass the same arguments as the success callback was originally called with.

success: function()
{
    callbackOne.apply(this, arguments);
    callbackTwo.apply(this, arguments);
}

see .apply() method.

see arguments property.

Also as a side note never ever put database usernames and passwords in javascript. Since anybody can access it.

Upvotes: 2

Related Questions