简体   繁体   中英

$.when().then() not working with nested ajax calls

I have been trying to scroll the page to a dynamic div that is created by the an ajax call.

When #divnotifications div clicked (below), I make the first ajax call that adds the Post details, then within this ajax call, another ajax call is made to add the related comments to the div.

The part explained so far works great. Then, I use $.when().then() to scroll to a div item created based on the ajax calls. However, the page does not scroll to the element that was created by LoadCommentsForPost ajax call.

Did I get the logic of $.when().then() wrong?

    $(document).on('click', '#divnotifications div', function (event) {
          event.preventDefault();
          $.ajax({
              //other details
              success: function (postid) {
                  $.when(DisplayPostWithFullDetails(postid)).then(function () {                            
                      //scroll to the content created by 
                      //LoadCommentsForPost function nested 
                      //inside DisplayPostWithFullDetails
                  });
              }
          });                
    });

    function DisplayPostWithFullDetails(postId) {
         $.ajax({
            //other details
            success: function (post) {
                //The code to build the div to display the post -- working fine
                LoadCommentsForPost(post.PostId);                

            }
        });
    }

    function LoadCommentsForPost(postid) {
        $.ajax({
            //other details
            success: function (response) {
                var comments = JSON.parse(response);
                DisplayComments(comments);//builds the div to display the comments - working fine
            }
        });
    }

UPDATED CODE

After receiving some feedback, I ended up with the following code. However, it is still not working. It works only if I add some delay to make sure the div is loaded:

    $(document).on('click', '#divnotifications div', function (event) {
        event.preventDefault();
        $.ajax({
            //other ajax stuff
             success: function (postid) {
                  DisplayPostWithFullDetails(postid).done(function () {
                          setTimeout(function () {
                              var scrollto = $("div[data-" + type.toLowerCase() +  "displayform='" + relateditem + "']").offset().top;
                              $("html, body").animate({ scrollTop: scrollto }, 600);
                          }, 500);
                  });
             }
        });
    });

    function DisplayPostWithFullDetails(postId) {
        jQuery.support.cors = true;
        return $.ajax({
            //other ajax stuff
            success: function (post) {
                post = JSON.parse(post);
                //display the post details

                LoadCommentsForPost(post.PostId);
            }
        });
    }

    function LoadCommentsForPost(postid) {
        var promise = new $.Deferred();
        jQuery.support.cors = true;
        $.ajax({
            //other ajax stuff
            success: function (response) {
                var comments = JSON.parse(response);
                DisplayComments(comments);//this is not ajax 

                promise.resolve('loadedcomments');
            }
        });

        return promise;
    }

Did I get the logic of $.when().then() wrong?

Yes, you need to return a promise from the functions if you want to use the function with $.when :

function DisplayPostWithFullDetails(postId) {
     return $.ajax({...
//   ^^^^^^

That said, wrapping a single promise in $.when is useless.

$.when(DisplayPostWithFullDetails(postid)).then(function () {

should just be:

DisplayPostWithFullDetail(postid).then(function () {

Did I get the logic of $.when().then() wrong?

No, but you are NOT returning the promise so you can't use the promise functions like .then().

UPDATE:

I use $.when().then() to scroll to a div item created based on the ajax calls. However, the page does not scroll to the element that was created by LoadCommentsForPost ajax call.

For me this means that you need to wait that both ajax calls are resolved.

This fiddle show how it should work emulating the ajax call using setTimeout Fiddle .

Your code may look similar to:

function DisplayPostWithFullDetails(postId) {
   var promise = new $.Deferred();
   $.ajax({
       //other details
        success: function (post) {
           //The code to build the div to display the post -- working fine
           LoadCommentsForPost(post.PostId).then(function() {
               promise.resolve();
           });                

        }
    });
    return promise;
}

function LoadCommentsForPost(postid) {
    return $.ajax({
        //other details
        success: function (response) {
            var comments = JSON.parse(response);
            DisplayComments(comments);//builds the div to display the comments - working fine
        }
    });
}

Now when you execute the function DisplayPostWithFullDetails it return a promise. So you can use .then() method;

DisplayPostWithFullDetails(postid)).then(function () {});

or...

var promise = DisplayPostWithFullDetails(postid);
promise.then(function(data){});

Also the major advantage of use $.when() is that you can execute the .then() method when all the promises that you pass to it are resolved.

There are not need to use it when you are waiting for a single promise.

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