嵌套的AJAX调用列表和$ .when.apply - 延迟的promise不能正常工作

时间:2015-01-16 03:38:32

标签: javascript jquery ajax promise jquery-deferred

我试图制作一系列三层嵌套的AJAX调用;基本结构如下(我省略了失败的电话)。

使用eventCalls进入第二级。最终when.apply.done仅在每次调用event.eventUsers.href完成后触发,如预期的那样。但是第三个ajax调用,即检索用户信息的event.eventUser.href调用内部的调用,在when块中的console.log之后执行。我确定我不完全理解延迟/承诺概念,任何人都可以解决这个问题吗?谢谢!

$.ajax({
  type: 'GET'
  url: '/api/events'
}).done(function(events, textStatus, jqXHR) {
  var eventCalls = [];
  $.each(events.items, function(index, event) {
    eventCalls.push(
      $.ajax({
        type: 'GET',
        url: event.eventUsers.href // Assoc objects for EventUser
        data: 'type=host' // Only one eventUser is returned
      }).done(function(eventUsers, textStatus, jqXHR) {
        // Getting the eventUser's user information
        $.ajax({
          type: 'GET',
          url: eventUsers.items[0].user.href
        }).done(function(user, textStatus, jqXHR) {
          event.host = user;
        })
      })
    )
  })
  $.when.apply($, eventCalls).done(function() {
    console.log(events);
  })
})

2 个答案:

答案 0 :(得分:1)

使用以下内容简化了整个过程:

  • $.get()代替$.ajax()
  • $.map()创建承诺数组

并更正:

  • .then()取代.done()全部通过
  • 来自.then回调的适当回报。
$.get('/api/events').then(function(events) {
    var queryString = 'type=host';//defined outside the $.map() loop for efficiency.
    var promises = $.map(events.items, function(item) {//$.map() loops through events.items and returns an array
        return $.get(item.eventUsers.href, queryString).then(function(eventUsers) {//note `return` 
            return $.get(eventUsers.items[0].user.href).then(function(user) {//note `return` 
                item.host = user;
                return item;//this return determines the value with which the final promise is resolved.
            });
        });
    });
    //at this point, `promises` is an array of promises each of which will be resolved when its `item.host` has been set
    $.when.apply(null, promises).then(function() {
        console.dir(events);
    });
});

答案 1 :(得分:0)

正如Bergi所指示的那样,解决方案是在嵌套的AJAX调用中用done替换then并将值return替换为done

thendone之间的区别在于then添加了处理程序并返回相同的承诺,而then添加了处理程序并返回一个新的承诺,当您从eventCalls.push( $.ajax({ type: 'GET', url: event.eventUsers.href, data: 'type=host' }).then(function(eventUsers) { // `then` chaines promises return $.ajax({ // Promises chain with return values type: 'GET', url: eventUsers.items[0].user.href }).then(function(user, textStatus, jqXHR) { event.host = user; // synchronous so no big deal done would work }).then(function(){ return event; }); // resolve with event to show }) ) 结算的内容时,该承诺会解决。

.map

作为提示 - 您可以使用.each代替{{1}}。