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

时间:2010-01-07 14:58:57

标签: javascript jquery ajax asynchronous scope

和我之前的其他人一样,我在Javascript中与范围挣扎。 (那并尝试阅读这些蠢货)。我已经检查过这个问题的一些先前的线程,但我似乎无法让它们正确地应用到我的issuue。 在下面的示例中,我想在完全填充数组后操纵tagsArr数组中的值。我将tagsArr变量声明在填充它的函数范围之外,以便全局访问它。但是变量似乎没有我期望的范围 - tagsArr.length在我将其输出到第16行的控制台时为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('<br />');
                    console.debug(tagsArr.length);
                });
                $('#total-dragged').append(data.photos.total);
                $('#types-dragged').append(tags);
            });
        });

6 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:2)

您对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('<br />'); 
                    console.debug(tagsArr.length); 
                }
            }); 
            $('#total-dragged').append(data.photos.total); 
            $('#types-dragged').append(tags); 
        }); 
    });

这可以假设照片的总数不超过默认的每页100个,否则你需要调整它。

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

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

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);
               });
         } 
      }
    });

答案 5 :(得分:0)

您可能需要查看this question I posted的答案。 javascript中有关于范围问题的一些很好的信息。