2010-01-07 54 views
2

和我之前的其他人一樣,我正在使用Javascript的範圍掙扎。 (那並試圖閱讀這些咒語)。我已經在這個問題上檢查了一些以前的線程,但我似乎無法讓他們正確地應用到我的發佈中。 在下面的例子中,我想操作tagsArr數組中的值,一旦數組完全填充。我聲明瞭tagsArr變量超出了它所填充的函數的範圍,以便全局訪問它。但是變量似乎並沒有有我希望的範圍 - 在tagsArr.length在我打電話輸出點爲0它上線16Javascript/jQuery變量沒有給出預期值

  $(function(){ 
      var apiKey = [myapikey]; 
      var tags = ''; 
      var tagsArr = new Array(); 
      $.getJSON('http://api.flickr.com/services/rest/?&method=flickr.people.getPublicPhotos&api_key=' + apiKey + '&[email protected]&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); 
      }); 
     }); 

回答

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 + '&[email protected]&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有一個問題的回調,直到所有內容都被拉出來,然後執行完成的代碼。

+0

謝謝!這是一個很好的解決方案。增加'totalFetched'變量(和相關的'if'子句)需要進一步向下移動一個子句,目前它正在計數標記而不是取回的照片! – fearoffours 2010-01-07 22:13:01

2

$ .getJSON是異步的(a在ajax中)。這意味着,當你到達console.debug()時,getJSON仍然變得越來越好。您需要在JSON回調中做一些額外的工作。

+1

旁註:OP * *在回調中工作。我認爲你的意思是你需要將某些工作「移動」到回調中。 – JPot 2010-01-07 15:05:45

+0

我喜歡保持簡短的線條 - 我沒有注意到該線末尾有一個回調!謝謝。 – Skilldrick 2010-01-07 15:08:13

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

這樣做的原因是,getJSON是一個異步請求。在調用$.getJSON之後,javascript引擎將立即移動到以下兩行代碼,並輸出您的數組的長度,此時爲零長度。直到此後getJSON請求才會收到響應,並將項目添加到數組中。

1

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

雖然這是一個可怕的解決方案。 – 2010-01-07 15:08:33

+0

但這是一個解決方案。 – mck89 2010-01-07 15:10:11

+1

應該有一個單獨的'$ .jax'功能:) – Skilldrick 2010-01-07 15:11:15