node.jsnode-request

Node.js keeps a copy of a global variable inside local scope


I have a Node.js application that uses the request library to GET a number of URLs. The code is something like this:

for(var i = 0; i < docs.length; i++){

        var URL = docs[i].url;

        request(URL, function(error, response, html){
            console.log(URL);
            // Other code...
}

For the sake of simplicity, let’s say docs contain URLs like [URL1, URL2, URL3, ...]. With the first iteration, URL = URL1 and a request is sent to that URL. With the second iteration, a request is sent to URL2 and so on. However, at the end of the loop, URL = URLn. Inside the event complete function, when I log URL, I always get URLn. However, I need to able to get the respective URLs that is [URL1, URL2, URL3, ...].

Any idea, how I can maintain a local copy of the URL, that remains unchanged event when the global URL gets changed?

This must be something easy, but I can't figure it out.


Solution

  • Just wrap the code in a function or use forEach. This happens because of closure scope.

    docs.forEach(functiom(doc) {
        var URL = doc.url;
    
        request(URL, function(error, response, html){
             console.log(URL);
             // Other code...
        })
    });
    

    Another fix

    for(var i = 0; i < docs.length; i++){
        makeRequest(docs[i]);
    }
    
    function makeRequest(doc) {
        var URL = doc.url;
    
        request(URL, function(error, response, html){
            console.log(URL);
        });
    }
    

    And another a bit more uglier fix with a closure inside the for loop

    for(var i = 0; i < docs.length; i++){
        (function(doc) {
            var URL = doc.url;
    
            request(URL, function(error, response, html){
                console.log(URL);
                // Other code...
            });
        })(docs[i]);
    }
    

    If you use something like JSHint, it will warn you not to create functions inside for loops as it will cause problems like this.