Javascript / jQuery变量没有给出期望值

像我之前的其他人一样,我在Javascript中与范围挣扎。 (那并尝试阅读这些令人讨厌的东西)。 我已经检查过这个问题的一些先前的线程,但我似乎无法让它们正确地应用到我的issuue。 在下面的示例中,我想在完全填充数组后操作tagsArr数组中的值。 我将tagsArr变量声明在填充它的函数范围之外,以便全局访问它。 但是这个变量似乎没有我期望的范围 – 在我调用第16行将控制输出到控制台的地方, tagsArr.length为0。

  $(function(){ var apiKey = [myapikey]; var tags = ''; var tagsArr = new Array(); $.getJSON('http://api.flickr.com/services/rest/?&method=flickr.people.getPublicPhotos&api_key=' + apiKey + '&user_id=46206266@N05&extras=date_taken,tags&format=json&jsoncallback=?', function(data){ $.each(data.photos.photo, function(i, item) { var photoID = item.id; $.getJSON('http://api.flickr.com/services/rest/?&method=flickr.photos.getInfo&api_key=' + apiKey + '&photo_id=' + photoID + '&format=json&jsoncallback=?', function(data){ if (data.photo.tags.tag != '') { $.each(data.photo.tags.tag, function(j, item) { tagsArr.push(item.raw); }); } }); tags = tagsArr.join('
'); console.debug(tagsArr.length); }); $('#total-dragged').append(data.photos.total); $('#types-dragged').append(tags); }); });

您对getJSON的调用是异步的。 因此,到达console.debug行时,对内部getJSON的所有调用仍然是未完成的。 因此,数组长度仍为0。

最后的getJSON调用完成后,您需要运行一些额外的代码。

  $(function(){ var apiKey = [myapikey]; var tags = ''; var tagsArr = new Array(); $.getJSON('http://api.flickr.com/services/rest/?&method=flickr.people.getPublicPhotos&api_key=' + apiKey + '&user_id=46206266@N05&extras=date_taken,tags&format=json&jsoncallback=?', function(data){ var totalExpected = data.photos.total; var totalFetched = 0; $.each(data.photos.photo, function(i, item) { var photoID = item.id; $.getJSON('http://api.flickr.com/services/rest/?&method=flickr.photos.getInfo&api_key=' + apiKey + '&photo_id=' + photoID + '&format=json&jsoncallback=?', function(data){ if (data.photo.tags.tag != '') { $.each(data.photo.tags.tag, function(j, item) { tagsArr.push(item.raw); totalFetched += 1; if (totalFetched == totalExpected) fetchComplete(); }); } }); function fetchComplete() { tags = tagsArr.join('
'); console.debug(tagsArr.length); } }); $('#total-dragged').append(data.photos.total); $('#types-dragged').append(tags); }); });

假设照片的总数不超过默认的100页,这是有效的,否则你需要调整它。

这就是说我不认为使用.each来解决大量的getJSON请求是非常有意义的。 我会重构它,以便在任何时候只有一次调用getJSON。 让一个问题回调下一张照片的下一个getJSON,直到所有照片被拉出然后完成你完成的代码。

$ .getJSON是异步的(ajax中的a)。 这意味着当你到达console.debug()时,getJSON仍然会得到。 您需要在JSON回调中做一些额外的工作。

原因是getJSON是一个异步请求。 在调用$.getJSON ,javascript引擎将立即移动到以下两行代码,并将输出数组的长度,到那时为零长度。 直到那之后, getJSON请求才会收到响应,并将项添加到数组中。

getJSON函数是异步的,因此当您调用debug函数时,数组仍然为空,因为请求未完成。 使用$ .ajax函数并设置async:false,它将起作用。

  $.ajax({ type: "GET", url: 'http://api.flickr.com/services/rest/?&method=flickr.photos.getInfo&api_key=' + apiKey + '&photo_id=' + photoID + '&format=json&jsoncallback=?', dataType: "json", async:false, success:function(data){ if (data.photo.tags.tag != '') { $.each(data.photo.tags.tag, function(j, item) { tagsArr.push(item.raw); }); } } }); 

这不是范围问题 – 问题是getJSON是异步的,所以它在将请求发送到flickr后立即继续执行。 当浏览器执行console.debug ,请求尚未返回,并且您尚未完成处理响应(因此尚未将任何项目推送到数组中)。

要解决此问题,请找到应该在arrays已满时执行的所有代码,并将其移动到getJSON回调方法中:

 if (data.photo.tags.tag != '') { $.each(data.photo.tags.tag, function(j, item) { tagsArr.push(item.raw); }); tags = tagsArr.join('
'); console.debug(tagsArr.length); $('#total-dragged').append(data.photos.total); $('#types-dragged').append(tags); }

您可能想查看我发布的这个问题的答案。 关于javascript中的范围问题,有一些很好的信息。