0

I'm trying to us Async.js to process an array of items. Is there some cute way to get this to work properly? If you're smarter than I, you'd except that because of the deferred execution, http://3 gets printed three times.

jsFiddle link

var a_servers = ['http://1', 'http://2', 'http://3'];

var a_actions = [];

for (var i = 0; i < a_servers.length; i += 1)
{
    var server = a_servers[i];

    a_actions.push(function(callback)
    {
        document.write(server  + '<br/>');
        callback(false, server );
    });
}

async.series(a_actions, function(err, a_servers)
{
    document.write('processed ' + a_servers.length + ' servers<br>');
    console.info(a_servers);
});​

1 Answer 1

1

You have a classic closure scope issue. You need to pass the server variable from the outer scope to the inner scope to get the desired behavior. You can use an IIFE for this.

for (var i = 0; i < a_servers.length; i += 1)
{
    var server = a_servers[i];

    a_actions.push((function(server) {
        return function(callback) {
            document.write(server  + '<br/>');
            callback(false, server );

    })(server));
}
Sign up to request clarification or add additional context in comments.

2 Comments

Gah, thanks, just figured it out and came back to ask if there was an easier way. jsfiddle.net/gYZhw/2
My general pattern is to define a top level function that defines and returns the closure, with the closure taking ("closing over") the interesting parameters as part of the closure scope of the top-level function. Then it clearly separates your closure scope complexity from what the loop is trying to accomplish/build. So you end up with a_actions.push(makeWriter(server));, which is clearer I think.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.