0
votes

I have struggle through this stack about my problem but still, I can't find any possible answer. Here is my problem and my current (bad) solution for it

I have an URL called URL1, after successfully retrieve data from this URL by ajax (called ajax1) , I perform another ajax (called ajax2) with URL2. If ajax2 is successful, I need to perform ajax1 again, with the same data with the first call. The below code is my current implementation, assume I have called ajax1 first time successfully.

...
ajax1: function () {
    var ajaxPost = $.ajax({
        type: "POST",
        url: myUrl,
        contentType: "application/json; charset=utf-8",
        data: myData
    });
    return ajaxPost;
},
ajax2: function (url, data, async) {
        var ajaxPost = $.ajax({
            type: "POST",
            url: url,
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify(data),
            dataType: 'json',
            async : async
        });
        return ajaxPost;
    },
...
var ajax2 = ajax2(**URL2**, myDataObject,**false**)
ajax2.done(function(data, textStatus, xhr) {
            ajax1();
            if(data.status === "success") {
                $('#success').html(data.message);
                $('#success').show();
            } else {
                $('#error').html(data.message);
                $('#error').show();
            }
        });

As we can see in the code snippet above, async of ajax2 is set to false. With this implementation, after successfully return of ajax2 and program run into .done() callback, ajax1 can successfully perform too.

I know this implementation is bad pratice since it's blocking UI. I want to do this request asynchronously but if I set async of ajax2 to true, after successfully return of ajax2 and program run into .done() callback, the ajax1 can't send its request to server. It seems like browser blocks this request since my breakpoint in server-side can't catch anything and ajaxPost variable of ajax2 is

Object {readyState: 0, status: 0, statusText: "canceled"}

I feel like I have missed something really important and really basic, so any help would be appreciate.

****UPDATE1**** To be more specific: I can chain ajax2 after ajax1 by using .then() and $.Deferred(). The chain runs just like what I expect, but the ajax request of ajax2 is still canceled by the browser. Here is the code using .then()

var ajax2 = ajax2(**URL2**, myDataObject,**false**)
        ajax2.done(function(data, textStatus, xhr) {
                    if(data.status === "success") {
                        $('#success').html(data.message);
                        $('#success').show();
                    } else {
                        $('#error').html(data.message);
                        $('#error').show();
                    }
                }).then(function(){
                    ajax1();
                });

Using $.Deferred()

var ajax2 = ajax2(**URL2**, myDataObject,**false**);
var dfrd = $.Deferred();
        ajax2.done(function(data, textStatus, xhr) {
                    if(data.status === "success") {
                        $('#success').html(data.message);
                        $('#success').show();
                    } else {
                        $('#error').html(data.message);
                        $('#error').show();
                    }
                    dfrd.resolve();
                })

         dfrd.then(function(){
                    ajax1();
                });
2
Never, ever, use async: false. Provide the ajax2() function as a callback of ajax1()Rory McCrossan
Hi RoryMcCrossan Could you please be more specific? As you can see, I have put ajax2() as a callback of ajax1() but it didn't work.Piel
Your example doesn't call ajax1(), and it doesn't accept any callback params? There's plenty of examples of how to do this if you search, for example: stackoverflow.com/questions/16384841/…Rory McCrossan
I thought that using .done() is equivalent with successful: declaration of $.ajax()? I have tried **successful:** declaration of **$.ajax()**, though. But it didn't work, the request is still canceled by browser.Piel

2 Answers

0
votes

Why dont you use result from last ajax to hold the control in ajax2.done(). Like this:

var ajax2 = ajax2(**URL2**, myDataObject)
        ajax2.done(function(data, textStatus, xhr) {
               var result = ajax1();
               result.done(function(){
                    if(data.status === "success") {
                        $('#success').html(data.message);
                        $('#success').show();
                    } else {
                        $('#error').html(data.message);
                        $('#error').show();
                    }
               });
           });

I hope it helps

0
votes

For anyone stops by, I have resolved this problem.

...
ajax1: function () {
    var ajaxPost = $.ajax({
        type: "POST",
        url: myUrl,
        contentType: "application/json; charset=utf-8",
        data: myData
    });
    return ajaxPost;
},
ajax2: function (url, data, async) {
        var ajaxPost = $.ajax({
            type: "POST",
            url: url,
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify(data),
            dataType: 'json',
            async : async
        });
        return ajaxPost;
    },
...
var ajax2 = ajax2(**URL2**, myDataObject,**false**)
ajax2.done(function(data, textStatus, xhr) {
            setTimeout(function() {
                ajax1();
            }, 0);
            if(data.status === "success") {
                $('#success').html(data.message);
                $('#success').show();
            } else {
                $('#error').html(data.message);
                $('#error').show();
            }
        });

The setTimeout magic comes to rescue. I don't really know why this solution work. By my inspection so far, it seems that .done() call back is not done enough, there is something that browser still needs to process after ajax2() finishes. When ajax1() is called in .done() call back, browser simply reject this request because it still hasn't done its business with ajax2() yet. By using setTimeout, I place ajax1() at the end of execution queue, thus providing browser with time to complete everything before execute ajax1().