简体   繁体   中英

Nested AJAX Calls using .done

I'm fairly new to AJAX, but working on a project that requires an ajax call to validate a specific value, then make another ajax call if the first returns the expected value. I am trying to implement the .done/.fail model, but can't find a way to prevent both calls from happening simultaneously, rather than once the first call is done and successful.

The following code will call the ajaxCall function twice, but concurrently rather than consecutively. I have researched a ton of code, including Nested AJAX Calls , jQuery getting rid of nested ajax functions , and $.when.done callback isn't working , but none seem to fit my exact scenario, or maybe I just don't understand the code. Either way, I haven't been able to find a solution, and any help will be much appreciated!

var xReturn = ajaxCall("1");    

xReturn.done(function(msg){
    console.log("callback "+msg+" successful");

    // if successful, place second call
    if(parseInt(msg)==1)
        xReturn = ajaxCall("2");    
});


function ajaxCall(mop){
    return $.ajax({
         url: "getItem.php",
         type: "POST",
         data: {code: '<?php echo $code; ?> ', op:mop}
    });
}

It seems like promises may be the way to go, but I can't wrap my head around how to use them in this scenario. Thanks in advance for any pointers in the right direction.

Update:

I ran through a battery of tests with different results. For my final test last night, I placed another console.log(msg); directly after ajaxCall("2"); Each time the resulting msg was always "1", leading me to believe the calls were not happening properly. This result tells me that xReturn.done(function(msg)... is only being called once, but I thought it would be called with each ajax call.

With this new information, I will perform additional testing tonight and report back.
Thanks

You need to bind a .done() method to each promise. xReturn.done() binds a function to that promise.

When you do xReturn = ajaxCall("2"); , you are replacing xReturn with a different object. This object does not have a .done() method bound to it.

You need to bind .done() to each promise, that doesn't happen automatically.

var xReturn = ajaxCall("1");
// This binds the callback to this *specific* promise    
xReturn.done(ajaxDone);    

function ajaxCall(mop){
    return $.ajax({
         url: "getItem.php",
         type: "POST",
         data: {code: '<?php echo $code; ?> ', op:mop}
    });
}

function ajaxDone(msg){
    console.log("callback "+msg+" successful");

    // if successful, place second call
    if(parseInt(msg)==1){
        xReturn = ajaxCall("2");

        // Bind a callback to this *new* object
        xReturn.done(ajaxDone);
    }
}

There are multiple ways to go about this problem.

You could simply call the second ajax call from the success of the first. Something on the following lines

function ajaxCall(mop){
    $.ajax({
         url: "getItem.php",
         type: "POST",
         data: {code: '<?php echo $code; ?> ', op:mop}
    }).done(function(msg) {
        console.log("First call is done. Received data as ", msg);
        if(parseInt(msg)==1) {
            $.ajax({
                //Repeat Options
            }).done(function(newMsg)) {
                console.log("We're done");
            };
        }
    });
}

}

If you do want to use the .done/.fail model, you could try using $.when . Here is a working fiddle that does consecutive calls using the same function.

function ajaxCall(mop){
    return $.ajax({
            url: "/echo/json/",
            type: "POST",
            data: {
                json: $.toJSON({data: mop}),
                delay: Math.floor(Math.random()*4)
            }
    });
}

$.when(ajaxCall("1")).done(function(data) {
    console.log("Done with first call. About to call second");
        if(data /* and add whatever conditions you need to call the next function */) {
            ajaxCall("2");
        }
});

Try it like this.

ajaxCall("1"); 

function ajaxCall(mop){
$.post( "getItem.php", {code: '<?php echo $code; ?> ', op:mop})
  .done(function( msg) {
    console.log("callback "+msg+" successful");
    if(parseInt(msg)==1)
        ajaxCall("2"); 
  });

}

And also you can use these with previous code

  .fail(function() {
    alert( "error" );
  })
  .always(function() {
    alert( "finished" );

How about that:

var xReturn1 = ajaxCall("1"),
    xReturn2 = ajaxCall("2");

$.when(xReturn1, xReturn2).done(function( a1, a2 ) {
    var data1 = a1[0], data2 = a2[0];
    console.log("Both done");
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM