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?

2
  • possible duplicate of Javascript infamous Loop problem? Commented Feb 12, 2014 at 1:56
  • "is not available inside the callback functions" --- what do you exactly mean? It is available Commented Feb 12, 2014 at 1:57

2 Answers 2

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.');
        });
});
Sign up to request clarification or add additional context in comments.

4 Comments

It would be an "issue" with i not urls. "urls could be null" -- it's not possible in JS
It is possible, just as in my example. But yes, there is ALSO a problem with i.
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.
PS: it is possible indeed. Not sure why I said that :-S
1

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

Comments

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.