2

I have a loop over some webpages and I want to check if they are available:

var urls = ['http://www.google.com', 'http://www.facebook.com'];
for(i in urls) {
    $http({method: 'GET', url: urls[i] })
            .success(function(data, status, headers, config) {
                console.log(urls[i] + ' is available.');
            })
            .error(function(data, status, headers, config) {
                console.log(urls[i] + ' is NOT available.');
            });
}

but urls[i] is not available inside the callback functions how do I make is accessible?

nickponline
  • 25,354
  • 32
  • 99
  • 167
  • possible duplicate of [Javascript infamous Loop problem?](http://stackoverflow.com/questions/1451009/javascript-infamous-loop-problem) – elclanrs Feb 12 '14 at 01:56
  • "is not available inside the callback functions" --- what do you exactly mean? It **is** available – zerkms Feb 12 '14 at 01:57

2 Answers2

3

Just based on that snippet, the urls variable should be available from within the functions. But there are some other things that are going on...that are probably causing the problem.

Since those methods are asynchronous, they will execute at some later point. So what could be happening is this:

var urls = ['http://www.google.com', 'http://www.facebook.com'];
for(i in urls) {
    $http({method: 'GET', url: urls[i] })
            .success(function(data, status, headers, config) {
                console.log(urls[i] + ' is available.');
            })
            .error(function(data, status, headers, config) {
                console.log(urls[i] + ' is NOT available.');
            });
}
// some time later...
urls = null;

Even worse, i inside your callbacks is not going to be what you expect it to be. The loop will execute first, and i will end up being (for both URLs) the last URL called. This is a classic case of scoping issues with asynchronous functions.

By the time the functions get around to executing, urls could be null, or used for something else. And, as already mentioned, i will not be what you expect it to be. Try wrapping the $http call in an immediately-invoked function expression (IIFE):

var urls = ['http://www.google.com', 'http://www.facebook.com'];
for(i in urls) {
    (function(urls, i){
        // urls now "captured" in function-scope variable
        $http({method: 'GET', url: urls[i] })
            .success(function(data, status, headers, config) {
                console.log(urls[i] + ' is available.');
            })
            .error(function(data, status, headers, config) {
                console.log(urls[i] + ' is NOT available.');
            });
    })(urls, i);
}

I would also like to point out that it's considered a bad idea to use for/in on arrays: you should change that to using a regular for loop with an index variable, or use .forEach. Here's how I would do it (which also, handily, eliminates the IIFE):

var urls = ['http://www.google.com', 'http://www.facebook.com'];
urls.forEach(function(url){
    $http({method: 'GET', url: url })
        .success(function(data, status, headers, config) {
            console.log(url + ' is available.');
        })
        .error(function(data, status, headers, config) {
            console.log(url + ' is NOT available.');
        });
});
Ethan Brown
  • 26,892
  • 4
  • 80
  • 92
  • It would be an "issue" with `i` not `urls`. "urls could be null" -- it's not possible in JS – zerkms Feb 12 '14 at 01:59
  • It is possible, just as in my example. But yes, there is ALSO a problem with `i`. – Ethan Brown Feb 12 '14 at 02:01
  • No, it's absolutely possible. I just tried it to make sure I wasn't going crazy. Sure enough, it's possible. If `urls` is set to `null`, and THEN the callbacks execute, `urls` will be null inside them. You try it. – Ethan Brown Feb 12 '14 at 02:04
  • 1
    PS: it is possible indeed. Not sure why I said that :-S – zerkms Feb 12 '14 at 02:04
1

You could get the url from "config.url" inside the callback.

Mardie
  • 1,663
  • 17
  • 27