开发者

closure inside a for loop - callback with loop variable as parameter [duplicate]

This question already has answers here: JavaScript closure inside loops – simple practical example (44 answers) Closed 6 years ago.

I am using jQuery "GET" in a loop to obtain several results from the server. I want to include the loop index as a fixed parameter to the call back but its not working.

(I followed the advice of this article on how 开发者_运维技巧to do it.)

However, the value I get in the call back is completely not what I expect – rather than each loop index value, it is always equal to the exit value of the index.

ie. the code fragment here prints out '16' for each execution of the callback. How do I get it to print 1, 2, 3... (I realize the order might be different, that's fine)

In addition to the code below, I've tried several ways to specify the call back function, eg. function(data, textStatus) { return test(data, textStatus, idx); }, 'text'); etc.

How is this supposed to work?

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


This is a pretty standard problem with closures. When you do this:

function(data, textStatus) { test(data, textStatus, idx); }

You're binding a reference to idx but not to the value of idx. So, by the time your callback gets called, the loop will have finished and idx will be 16 in all of the callbacks that you bound.

The usual solution is to force evaluation of idx through a function call:

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

You can also inline the function with a self-executing function if you want to keep it all together:

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

The function call gives you the value of idx when the function is called and that's the value of idx that you want.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜