Замыкание внутри цикла for - обратный вызов с переменной цикла в качестве параметра
Я использую jQuery "GET" в цикле, чтобы получить несколько результатов с сервера. Я хочу включить индекс цикла в качестве фиксированного параметра для обратного вызова, но он не работает.
(Я последовал совету этой статьи о том, как это сделать.)
Однако значение, которое я получаю при обратном вызове, совсем не то, что я ожидаю - вместо каждого значения индекса цикла оно всегда равно выходному значению индекса.
то есть. фрагмент кода здесь выводит "16" для каждого выполнения обратного вызова. Как мне заставить его напечатать 1, 2, 3... (я понимаю, что порядок может быть другим, это нормально)
В дополнение к приведенному ниже коду я попробовал несколько способов указать функцию обратного вызова, например. function(data, textStatus) { return test(data, textStatus, idx); }, 'text');
и т.п.
Как это должно работать?
function test(data, textStatus, siteNo)
{
console.log("siteNo=" + siteNo);
}
function loadConfigLists()
{
var siteReport;
// retrieve site configuration
jQuery.get("svGetSiteConfig.php", function(data, textStatus)
{
// retrieve port configuration for all sites
for (var idx=1; idx<=15; idx++)
{
var probeIP = siteConfigArray[idx].siteIP;
if (probeIP != "" && probeIP != null)
jQuery.get("svGetPortInfo.php?svSiteIpAddr=" + probeIP+"&s="+idx,
function(data, textStatus) { test(data, textStatus, idx); }, 'text');
else // IP value is blank
siteConfigArray[idx].portManifest = null;
}
}
}, 'text');
}
1 ответ
Это довольно стандартная проблема с замыканиями. Когда вы делаете это:
function(data, textStatus) { test(data, textStatus, idx); }
Вы связываете ссылку на idx
но не к стоимости idx
, Таким образом, к тому времени, когда ваш обратный вызов будет вызван, цикл завершится и idx
будет 16 во всех обратных вызовов, которые вы связали.
Обычное решение состоит в том, чтобы форсировать оценку idx
через вызов функции:
function build_callback(idx) {
return function(data, textStatus) {
test(data, textStatus, idx);
};
}
// And then...
jQuery.get("svGetPortInfo.php?svSiteIpAddr=" + probeIP+"&s="+idx, build_callback(idx), 'text');
Вы также можете встроить функцию в самовыполняющуюся функцию, если хотите сохранить все вместе:
for (var idx=1; idx<=15; idx++)
(function(idx) {
var probeIP = siteConfigArray[idx].siteIP;
if (probeIP != "" && probeIP != null)
jQuery.get("svGetPortInfo.php?svSiteIpAddr=" + probeIP+"&s="+idx,
function(data, textStatus) { test(data, textStatus, idx); }, 'text');
else // IP value is blank
siteConfigArray[idx].portManifest = null;
})(idx);
Вызов функции дает вам значение idx
когда функция вызывается, и это значение idx
что ты хочешь.