Reputation: 2160
I want to get image dimensions and afterwards perform more actions. As image onload is asynchronous I have decided to do everything in the onload call. This is what I have right now:
function getMeta(url, callback) {
var img = new Image();
img.src = url;
img.onload = function() { callback(this.width, this.height); };
}
// ajax response this some info:
function(res) {
var totalFound = res.data.length;
var photo = [];
for (var i = 0; i < totalFound; i++) {
var full = res.data[i].urls.raw;
var thumb = res.data[i].urls.thumb;
var user = res.data[i].user.name;
var links = res.data[i].user.links.html;
getMeta(thumb,function(width, height) {
console.log(width + 'px ' + height + 'px')
photo.push({
full: full,
thumb: thumb,
user: author,
link: links
width: this.width
});
});
};
};
The problem is that variables full, thumb, user and links are not available in the getMeta callback. How to get over this?
Upvotes: 0
Views: 116
Reputation: 7480
The problem is that those variables are scoped outside the for
loop, meaning they're updated, rather than declared, in every successive iteration and every callback will see the final state of them since they're all invoked some time after the for
loop has completed.
If you replace your for
loop with a forEach
, you will create a new scope for each iteration and the variables will be scoped the way you want them to:
function(res) {
var photo = [];
res.data.forEach(function(item) {
var full = item.urls.raw;
var thumb = item.urls.thumb;
var user = item.user.name;
var links = item.user.links.html;
getMeta(thumb,function(width, height) {
console.log(width + 'px ' + height + 'px')
photo.push({
full: full,
thumb: thumb,
user: author,
link: links,
width: this.width
});
});
});
};
If you have the option of using ES6 syntax, an alternative is to simply use let
instead of var
which will properly scope the variables to each iteration.
Upvotes: 2