0

I'm new to NodeJS and I was trying to figure out stuff but unfortunately I couldn't find information on it with my knowledge.

Basicly, I want to use a variable from a function inside another function wich is a child of the main function.

Here is my code :

http.get(url, function(res) {
var body = '';

res.on('data', function(chunk) {
    body += chunk;
});

res.on('end', function() {
    var jsonResult = JSON.parse(body);
    for (var i=0;i<5;i++)
    {
        gameId = jsonResult.gameList[i].gameId;
        url = 'http://somesite.com/' + gameId + '/0/token';
        http.get(url, function(res) {
            var body = '';

            res.on('data', function(chunk) {
                body += chunk;
            });

            res.on('end', function() {
                jsonRes = JSON.parse(body);
                switch(i)
                {
                    case 0:
                        var elo0 = jsonRes.interestScore;
                        module.exports.elo0 = elo0;
                        break;
                    case 1:
                        var elo1 = jsonRes.interestScore;
                        module.exports.elo1 = elo1;
                        break;
                    case 2:
                        var elo2 = jsonRes.interestScore;
                        module.exports.elo2 = elo2;
                        break;
                    case 3:
                        var elo3 = jsonRes.interestScore;
                        module.exports.elo3 = elo3;
                        break;
                    case 4:
                        var elo4 = jsonRes.interestScore;
                        module.exports.elo4 = elo4;
                        break;

                }


        });
        }).on('error', function(e) {
            console.log("Got error: ", e);
        });

    }

});
}).on('error', function(e) {
  console.log("Got error: ", e);
});

Note that I didn't include everything, just the problematic part. I want to use the variable i from the loop inside the switch but it doesn't work.

6
  • Move the inner part of the loop into its own function and call it passing in i (and anything else you need). This is a classic js problem - referencing a loop counter inside an asynch Commented Aug 8, 2013 at 4:14
  • Could you please give me an example on that? I'm not quite sure I understand where to move the loop. Commented Aug 8, 2013 at 4:21
  • For future reference. Perhaps, the answer is easy, but I think you can scrape the code (omit unnecesary part to show the structure) to present what exactly you need. 'use the variable i from the loop inside the switch. is not that clear. Commented Aug 8, 2013 at 4:22
  • Here is a better explanation: jslinterrors.com/dont-make-functions-within-a-loop I will post an example a bit later unless someone else beats me to it. Commented Aug 8, 2013 at 4:29
  • I tought I needed to make the function within a loop because I would actually need it at this part of the code : gameId = jsonResult.gameList[i].gameId; Commented Aug 8, 2013 at 4:36

1 Answer 1

3

The problem here is that you are referencing i in your switch statement within an asynchronous callback. When you do this, you won't get the value of i at the time the function is created, but the final value of i at the end of the loop iteration.

There are a couple of ways to fix this - both involve trapping the current loop value of i in a closure for later reference by the callback.

for example:

for (var i=0;i<5;i++)
{
    (function(idx) {
        gameId = jsonResult.gameList[idx].gameId;
        url = 'http://somesite.com/' + gameId + '/0/token';
        http.get(url, function(res) {
            ...

            res.on('end', function() {
                jsonRes = JSON.parse(body);
                switch(idx)
                {
                    case 0:
                      break;

                    ...
                }
            });
            ...
        });
    })(i);
}

Here, an anonymous function is created for each pass through the loop and called immediately passing the current value of the loop counter i as the incoming parameter idx.

Another approach (as mentioned in the comments above) is to refactor the inner part of your loop into a separate function and call it passing all necessary context:

function scoreHandler(jsonResult, idx) {
    var gameId = jsonResult.gameList[idx].gameId;
    var url = 'http://somesite.com/' + gameId + '/0/token';
    http.get(url, function(res) {
        ...

        res.on('end', function() {
            jsonRes = JSON.parse(body);
            switch (idx) {
               ...
            }
        });
    })
    .on('error', function(e) {
        console.log("Got error: ", e);
    });
}

Your refactored loop would look something like:

res.on('end', function() {
    var jsonResult = JSON.parse(body);
    for (var i = 0; i < 5; i++) {
        scoreHandler(jsonResult, i);
    }
});
Sign up to request clarification or add additional context in comments.

1 Comment

Closures, it's all about closures.

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.