0

繰り返し処理してリストのマークアップを作成しようとしているオブジェクトの配列があります。配列を使用して遅延リクエストを格納し、すべてのリクエストが完了した後に連結マークアップをDOMに挿入する場合は$.whenを使用しています。

コードは次のとおりです。

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

しかし、私は成功していません。私は2つの問題のうちの1つに遭遇しています:

  1. (上記のコードのように)遅延アイテムを関数でラップすると、リクエストは実行されませんが、$。when実行されます。ただし、リクエストが実行されなかったため、出力は空になります。
  2. 遅延アイテムを関数でラップしないと、リクエストが実行され(正しい回数ですが、コンソールに記録されるitem.idは常に最後のアイテムのIDです)、$。whenは実行されません。実行されます。

私はこれがこの質問に非常に似ていることを知っており、私はそのコードを私の基礎として使用していますが、私はまだこれらの問題を抱えています。何か案は?

4

1 に答える 1

2

このような関数でコードをラップすると、コードが実行されることはありません。配列にプッシュするのは関数への参照であり、AJAX呼び出しの結果ではありません。

コードを関数でラップしない場合、コードは実行されますがitem、コールバックでローカル変数を使用しているため、リクエストが到着したときではなく、応答が到着したときに変数が持つ値を使用します。送信されました。populateItemListリクエストは非同期であり、Javascriptはシングルスレッドであるため、関数から戻るまでコールバックは呼び出されません。したがって、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);
}
于 2013-02-01T20:28:55.017 に答える