Reputation: 25914
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?
Upvotes: 2
Views: 2984
Reputation: 27282
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.');
});
});
Upvotes: 3