多次承诺后需要返回结果

时间:2014-11-24 12:19:30

标签: javascript jquery jquery-deferred

当我调用此函数时,它会立即返回结果,而不是在第三个promise之后延迟。我该怎么办?

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;
  },

3 个答案:

答案 0 :(得分:1)

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();
}

然后将getBlogs称为

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

但是,有更好的方法可以做到这一点。首先,你可以链接承诺。

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

最后,如果你真的要按照这样的顺序做多个异步事情,我可以推荐一下caolan优秀的异步库吗?这使得这样的思考变得更加容易。 https://github.com/caolan/async

答案 1 :(得分: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();
  },

答案 2 :(得分:0)

改进你已经提供的答案,你可以这样做,避免创建额外的延期,只使用$.when()已经返回的承诺。 :

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;
    });
  },

或者,您还可以使用$.when()的返回值来避免单独的ajax回调,如下所示:

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;
    });
  },