JSONP回调变量提升,作用域异常
JSONP Callback variable hoisting, scoping anomoly
我有一个全局数组,我想用 Flickr 上 JPEG 的 URL 填充。我打算在函数之间传递这个数组。
当我尝试从我的 JASONP 回调函数中读取数组(或 main.js:40 中的 console.log)的内容时,它似乎是空的。然而从浏览器控制台来看它似乎很好(屏幕截图)。我的 JASONP 回调似乎能够 array.push()
但无法读取 array[i].src
。
这是怎么回事?
我似乎误解了 JASONP 回调中变量的范围。有人可以启发我(用超级菜鸟外行的话说)这里发生了什么,并告诉我这应该是什么样子?
这里是 JSFiddle - 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
谢谢。
此代码:
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?
};
从不 调用 mycallback
函数,因此不会向 images
添加任何内容。 (另请注意,不要将 ;
放在附加到控制流语句(如 if
)的块的结束 }
之后。)
假设 UrlExists
期望您出于某种原因将回调传递给它并异步调用该回调,您需要实际将函数传递给它,并且您需要确保当函数被调用时,它是用正确的 furl
调用的(因为如果它被调用为异步的,您当前使用的 furl
将在调用回调之前被更改)。注释掉的代码中的 i
也是如此。有了这些假设,您可以这样做:
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
现在,UrlExists
回调中没有任何内容依赖于在回调发生之前会改变的东西,因为每次调用 forEach
都会创建一个新的、单独的 furl
回调。
我有一个全局数组,我想用 Flickr 上 JPEG 的 URL 填充。我打算在函数之间传递这个数组。
当我尝试从我的 JASONP 回调函数中读取数组(或 main.js:40 中的 console.log)的内容时,它似乎是空的。然而从浏览器控制台来看它似乎很好(屏幕截图)。我的 JASONP 回调似乎能够 array.push()
但无法读取 array[i].src
。
这是怎么回事?
我似乎误解了 JASONP 回调中变量的范围。有人可以启发我(用超级菜鸟外行的话说)这里发生了什么,并告诉我这应该是什么样子?
这里是 JSFiddle - 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
谢谢。
此代码:
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?
};
从不 调用 mycallback
函数,因此不会向 images
添加任何内容。 (另请注意,不要将 ;
放在附加到控制流语句(如 if
)的块的结束 }
之后。)
假设 UrlExists
期望您出于某种原因将回调传递给它并异步调用该回调,您需要实际将函数传递给它,并且您需要确保当函数被调用时,它是用正确的 furl
调用的(因为如果它被调用为异步的,您当前使用的 furl
将在调用回调之前被更改)。注释掉的代码中的 i
也是如此。有了这些假设,您可以这样做:
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
现在,UrlExists
回调中没有任何内容依赖于在回调发生之前会改变的东西,因为每次调用 forEach
都会创建一个新的、单独的 furl
回调。