I have a global array I want to populate with URLs to JPEGs at Flickr. I intend to pass this array around between functions.
When I try to read the contents of the array (or console.log from main.js:40) from within my JASONP callback function it appears to be empty. Yet from the browser console it seems fine (screen shot). My JASONP callback seems able to array.push()
but can't read array[i].src
.
What's going on here?
I seem to be misunderstanding how variables are scoped from JASONP callbacks. Can someone enlighten me (in super-noob laymen's terms) as to what's happening here and show me what this should look like?
JSFiddle here - http://jsfiddle.net/Nyquist212/7gtxetxj/
function UrlExists(url, callback) {
var http = new XMLHttpRequest();
http.open('HEAD', url);
http.onreadystatechange = function() {
if (this.readyState == this.DONE) {
callback(this.status = 200);
}
};
http.send();
};
var images = []; // Store imgs in here
$.getJSON("https://api.flickr.com/services/rest/?method=flickr.photos.search&jsoncallback=?",
{
api_key : "da2015d88b5eab3b3d7d989c13c4d430",
content_type : 1,
text : "landscape, beach, coast, surf, black, white",
format : "json",
per_page : 10
},
function jsonFlickrApi (results) { // my JSONP callback func
for (var i=0; i < results.photos.photo.length; i++) {
var farm = results.photos.photo[i].farm;
var id = results.photos.photo[i].id;
var server = results.photos.photo[i].server;
var secret = results.photos.photo[i].secret;
var furl = "https://farm" + farm + ".staticflickr.com/" + server + "/" + id + "_" + secret + "_m" + ".jpg";
if (!UrlExists(furl, mycallback)) {
function mycallback(results){
images.push({"src":furl});
};
$("<img />").attr("src", furl).appendTo("#one"); // This works...
//$("<img />").attr("src", images[i].src).appendTo("#one"); // Why wont this work?
};
}; // End for
console.log(images); // Returns empty!?!
} // End jsonFlickrApi
); // End getJSON
Thank you.
This code:
if (!UrlExists(furl, mycallback)) {
function mycallback(results) {
images.push({
"src": furl
});
};
$("<img />").attr("src", furl).appendTo("#one"); // This works...
//$("<img />").attr("src", images[i].src).appendTo("#one"); // Why wont this work?
};
never calls that mycallback
function, and thus nothing is ever added to images
. (Also note that you don't put ;
after the closing }
of the block attached to a constrol flow statement like if
.)
Assuming UrlExists
expects you to pass it a callback for some reason and calls that callback asynchronously, you'll need to actually pass the function to it, and you'll need to ensure that when the function is called, it's called with the right furl
(since if it's called asynchronous, the furl
you're currently using will have been changed before the callback is called). The same would be true of i
in your commented out code. With those assumptions in place, you can do this:
function jsonFlickrApi(results) { // my JSONP callback func
results.photos.photo.forEach(function(photo) {
var furl = "https://farm" + photo.farm +
".staticflickr.com/" +
photo.server + "/" +
photo.id + "_" +
photo.secret + "_m" + ".jpg";
UrlExists(furl, function() { // I assume this is called if the URL does exist, and that that's what you want
images.push({
"src": furl
});
$("<img />").attr("src", furl).appendTo("#one");
});
});
// Note that `images` will still be empty here, waiting for the callbacks
// from UrlExists
} // End jsonFlickrApi
Now, nothing in the UrlExists
callback is relying on something that will change before the callback occurs, because a new, separate furl
is created for every call to the forEach
callback.