Переменные Javascript / jQuery не дают ожидаемых значений - PullRequest
2 голосов
/ 07 января 2010

Как и другие до меня, я борюсь с областью в Javascript. (Это и пытается прочесть штопку). Я проверил некоторые из предыдущих тем по этому вопросу, но, кажется, не могу заставить их правильно применить к моей проблеме. В приведенном ниже примере я хочу манипулировать значениями в массиве tagsArr после того, как массив будет заполнен полностью. Я объявил переменную tagsArr вне области действия функции, в которой она заполнена, чтобы получить к ней глобальный доступ. Но переменная, кажется, не имеет ожидаемой области видимости - tagsArr.length равен 0 в точке, где я вызываю вывод ее на консоль в строке 16.

            $(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 ]

2 голосов
/ 07 января 2010

Ваши вызовы 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 голосов
/ 07 января 2010

$. GetJSON является асинхронным (a в ajax). Это означает, что к тому времени, когда вы добираетесь до console.debug (), getJSON все еще получает Вам потребуется проделать дополнительную работу в обратном вызове JSON.

1 голос
/ 07 января 2010

Функция getJSON является асинхронной, поэтому при вызове функции отладки массив все еще пуст, поскольку запросы не выполнены. Используйте функцию $ .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);
               });
         } 
      }
    });
1 голос
/ 07 января 2010

Причина этого в том, что getJSON является асинхронным запросом. после вызова $.getJSON движок javascript немедленно перейдет к следующим двум строкам кода и выведет длину вашего массива, которая к тому времени равна нулю. Только после этого запрос getJSON получает ответ и добавляет элементы в массив.

1 голос
/ 07 января 2010

Это не проблема области - проблема в том, что 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);
}
0 голосов
/ 07 января 2010

Возможно, вы захотите проверить ответ на этот вопрос, который я отправил . В javascript есть хорошая информация о проблемах с областью действия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...