0

When I call this function it returns a result immediately instead of delaying to after the third promise. What can I do??

getBlogs: function(blogId){
    var blogcomments = new Entities.BlogCommentCollection();
    var blogs = new Entities.BlogCollection();
    var defera = $.Deferred();
    var deferb = $.Deferred();
    var deferc = $.Deferred();
    var model;
    //alert(model);

    $.get("/lightning/presentation/blogs", function(val){
      defera.resolve(val);
    });

    var promisea = defera.promise();

    $.when(promisea).done(function(val){
      var models = initializeBlogs(JSON.parse(val));
      blogs.reset(models);
      model = blogs.at(blogId);
      //alert(JSON.stringify(model));
      $.get("/lightning/presentation/blogs/?blogId=" + blogId, function(full){
        deferb.resolve(full);            
      });
    });

    var promiseb = deferb.promise();

    $.when(promiseb).done(function(full){
      model.set('full', full);
      //alert(JSON.stringify(model));
      $.get("/lightning/presentation/blogs/?comments=" + blogId, function(res){
        deferc.resolve(res);             
      });
    });

    var promisec = deferc.promise();

    $.when(promisec).done(function(res){
      if(res.length === 0){
        blogcomments.reset();
      }else{
        //alert(res)
        var models = initializeBlogComments(JSON.parse(res));
        blogcomments.reset(models);
        model.set('comments', blogcomments)
        //return model;
      }
      currentBlog = model;
      alert(JSON.stringify(model));
      //return model;
    });
    //alert(JSON.stringify(model));
    return model;
  },
Alex Mbaka
  • 123
  • 8
  • possible duplicate of [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](http://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – hon2a Nov 24 '14 at 12:30

3 Answers3

1

Promises are async. They don't cause the current function to delay return (that would be sync). They return, well, a promise that will resolve at some point in the future.

So the most basic way to fix your code is to return not the model, but the promise

getBlogs: function(blogId) {
  var deferAll = $.Deferred();

  // your last set will then respond to them all
$.when(promisec).done(function(res){
  if(res.length === 0){
    blogcomments.reset();
  }else{
    //alert(res)
    var models = initializeBlogComments(JSON.parse(res));
    blogcomments.reset(models);
    model.set('comments', blogcomments)
    //return model;
  }
  currentBlog = model;

  // THIS is where it gets resolved
  deferAll.resolve(model);
});

  // do whatever you need to
  return deferAll.promise();
}

And then you call getBlogs as

getBlogs(25).then(function(model) {
  // model is given here
});

However, there are better ways to do this. First of all, you can chain promises.

$.get("/lightning/presentation/blogs/?blogId=" + blogId).then(function(full){...}).then().then() // etc

Lastly, if you really are going to do multiple async things in an order like that, may I recommend caolan's excellent async library? It makes thinks like this much easier. https://github.com/caolan/async

deitch
  • 14,019
  • 14
  • 68
  • 96
1
getBlog: function(blogId, model){
    var blogcomments = new Entities.BlogCommentCollection();
    var defer = $.Deferred();
    var fullBlog;

    $.when(

      $.get("/lightning/presentation/blogs/?blogId=" + blogId, function(full){
        fullBlog = full;       
      }),

      $.get("/lightning/presentation/blogs/?comments=" + blogId, function(res){
        var models = initializeBlogComments(JSON.parse(res));
        blogcomments.reset(models);          
      })

    ).done(function() {
      model.set('full', fullBlog);
      model.set('comments', blogcomments);
      defer.resolve(model);
    });
    return defer.promise();
  },
Alex Mbaka
  • 123
  • 8
0

Improving upon the answer you already provided, you can do it this way that avoids creating the extra deferred and just uses the promise that $.when() already returns. :

getBlog: function(blogId, model){
    var blogcomments = new Entities.BlogCommentCollection();
    var fullBlog;

    return $.when(

      $.get("/lightning/presentation/blogs/?blogId=" + blogId, function(full){
        fullBlog = full;       
      }),

      $.get("/lightning/presentation/blogs/?comments=" + blogId, function(res){
        var models = initializeBlogComments(JSON.parse(res));
        blogcomments.reset(models);          
      })

    ).then(function() {
      model.set('full', fullBlog);
      model.set('comments', blogcomments);
      return model;
    });
  },

Or, you could additionally use the return values from $.when() to avoid the separate ajax callbacks like this:

getBlog: function(blogId, model){
    var blogcomments = new Entities.BlogCommentCollection();

    return $.when(
      $.get("/lightning/presentation/blogs/?blogId=" + blogId),    
      $.get("/lightning/presentation/blogs/?comments=" + blogId)
    ).then(function(r1, r2) {
      model.set('full', r1[0]);
      var models = initializeBlogComments(JSON.parse(r2[0]));
      blogcomments.reset(models);          
      model.set('comments', blogcomments);
      return model;
    });
  },
jfriend00
  • 683,504
  • 96
  • 985
  • 979