我有一个对象数组,我正在尝试迭代并为其创建列表标记。我正在使用一个数组来存储延迟的请求,并且在完成所有请求之后将$。连接标记注入到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);
});
}
但是,我没有取得任何成功。我遇到了两个问题之一:
我知道这与this question非常相似,我正在使用该代码作为我的基础,但我仍然遇到这些问题。有什么想法吗?
答案 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);
}