$ .get表示延迟对象数组中的每个项目都不能正常工作

时间:2013-02-01 20:15:40

标签: jquery jquery-deferred jquery-get

我有一个对象数组,我正在尝试迭代并为其创建列表标记。我正在使用一个数组来存储延迟的请求,并且在完成所有请求之后将$。连接标记注入到DOM中。

以下是代码:

function populateItemList(items) {
  var output = '',
    item = null,
    template = null,
    defers = [];

  for (var i = 0, j = items.length; i < j; i++) {
    item = items[i];

    defers.push(function() {
      $.get('/item/' + item.id + '/template')
      .done(function(source) {
        template = Handlebars.compile(source);
        output += template(item);

        console.log(item.id + ': done');
      })
    });
  }

  $.when.apply(window, defers).done(function() {
    $('.itemListContainer').html(output);
    $('.itemList a').click(onItemLinkClick);

    console.log('when: ' + output);
  });
}

但是,我没有取得任何成功。我遇到了两个问题之一:

  1. 如果我 将延迟项目包装在一个函数中(如上面的代码中所示),则请求不会被执行,但$ .when 会执行。但由于请求未执行,因此输出为空。
  2. 如果我将延迟项目包装在一个函数中,请求将被执行(正确的次数,但记录到控制台的item.id始终是最后一个的id item),而$ .when 不会执行。
  3. 我知道这与this question非常相似,我正在使用该代码作为我的基础,但我仍然遇到这些问题。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

当您将代码包装在类似的函数中时,代码永远不会被执行。你推入数组的是对函数的引用,而不是AJAX调用的结果。

当你没有将代码包装在函数中时它会被执行,但是当你在回调中使用局部变量item时,你将使用变量在当时的值。响应到达,而不是在请求发送时。由于请求是异步的,并且因为Javascript是单线程的,所以在从populateItemList函数返回之前不会调用任何回调,因此item变量将始终是最后一项。

您应该将代码包装在一个函数中,这样可以为每次迭代创建一个item变量,但您也应该立即执行该函数,并将返回值推送到数组中:

for (var i = 0, j = items.length; i < j; i++) {

  var result = (function(item) {
    return $.get('/item/' + item.id + '/template')
    .done(function(source) {
      template = Handlebars.compile(source);
      output += template(item);
      console.log(item.id + ': done');
    });
  }(items[i]));

  defers.push(result);
}