最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Can't store data fetched with jQuery JSONP - Stack Overflow

programmeradmin1浏览0评论

I'm trying to fetch a bunch of photo data from Flickr via a jQuery AJAX call using JSONP, but I don't want to use the data right away. Instead, I'd like to preserve it for use later. In a plicated case, I'd like to let users perform different queries on the prefetched data. In a simpler case, I'd like to just load the next n images each time the user clicks a button.

Right now, I'm testing just the most basic functionality below, which is adapted from the best answer to this question: JQuery - Storing ajax response into global variable

However, the retrieved JSON data is not getting stored in the jsonData variable as it should. I put the alert statements to debug, and the strange thing is that the getData() alert is triggered before the alert in the callback function. Why is this happening?

var dataStore = ( function() {
  var jsonData;

  $.ajax({
    type: "GET",
    url: ".gne?jsoncallback=?",
    dataType: "json",
    data: {
      tags: "dog",
      tagmode: "any",
      format: "json"
    },
    success: function(data) {
      jsonData = data;
      alert(jsonData);
    }
  });

  return { getData : function()
  {
      if (jsonData) return jsonData;
      else alert("no data!");
  }};
})();

var stuff = dataStore.getData();

$.each(stuff.items, function(i,item) {
  $("<img/>").attr("src", item.media.m).appendTo("#images");
  if ( i == 3 ) return false;
});

I'm trying to fetch a bunch of photo data from Flickr via a jQuery AJAX call using JSONP, but I don't want to use the data right away. Instead, I'd like to preserve it for use later. In a plicated case, I'd like to let users perform different queries on the prefetched data. In a simpler case, I'd like to just load the next n images each time the user clicks a button.

Right now, I'm testing just the most basic functionality below, which is adapted from the best answer to this question: JQuery - Storing ajax response into global variable

However, the retrieved JSON data is not getting stored in the jsonData variable as it should. I put the alert statements to debug, and the strange thing is that the getData() alert is triggered before the alert in the callback function. Why is this happening?

var dataStore = ( function() {
  var jsonData;

  $.ajax({
    type: "GET",
    url: "http://api.flickr./services/feeds/photos_public.gne?jsoncallback=?",
    dataType: "json",
    data: {
      tags: "dog",
      tagmode: "any",
      format: "json"
    },
    success: function(data) {
      jsonData = data;
      alert(jsonData);
    }
  });

  return { getData : function()
  {
      if (jsonData) return jsonData;
      else alert("no data!");
  }};
})();

var stuff = dataStore.getData();

$.each(stuff.items, function(i,item) {
  $("<img/>").attr("src", item.media.m).appendTo("#images");
  if ( i == 3 ) return false;
});
Share Improve this question edited May 23, 2017 at 12:25 CommunityBot 11 silver badge asked Dec 2, 2011 at 8:01 stephjangstephjang 9591 gold badge9 silver badges13 bronze badges 4
  • It's best to ask one question in each question here on Stack Overflow. In the above, you're asking two quite distinct questions: 1) Why is your code not working as you expect, and separately 2) Should you be doing this or putting in hidden images. Conflating questions reduces the quality of both the question and its answers, best to split them up. – T.J. Crowder Commented Dec 2, 2011 at 8:17
  • I see, thanks for the tip. Should I split it up now, after the fact? – stephjang Commented Dec 2, 2011 at 8:29
  • @stchangg: I probably would, yeah. Since the other answer here addresses the "why doesn't this code work right" aspect, I'd leave that part here and ask the image best practices question separately. I can copy over the part of my answer that relates to that. – T.J. Crowder Commented Dec 2, 2011 at 8:35
  • Cool, just extracted out the other question here: stackoverflow./questions/8353733/… – stephjang Commented Dec 2, 2011 at 8:43
Add a ment  | 

2 Answers 2

Reset to default 7

...and the strange thing is that the getData() alert is triggered before the alert in the callback function. Why is this happening?

Because ajax calls in general are, by default, asynchronous — and JSONP calls are always asynchronous by their nature (other kinds of ajax calls can be made synchronous, but it's generally a bad idea).

This means your

var stuff= dataStore.getData();

line executes before the JSONP request pletes. This is also why it doesn't see anything in jsonData.

You need to move any processing of the JSONP call result into something called from the success callback of the request.

The problem is that stuff is undefined when $.each runs because stuff hasn't finished running yet. Everything needs to be in a callback. There's numerous ways to get around it from the most ugly and hacky of doing a setInterval() that checks if stuff === undefined and if NOT then it does the $.each to a more JS native way of just using callbacks.

Personally, I highly suggest you just use callbacks more effectively. Here's what i'd do. This should put you on the right track. Obviously a lot of this is faux code, but can easily be modified to your needs.

var cachedImageData = {}; //To check if data exists for the search term

var displayImages = function(stuff){
  $.each(stuff.items, function(i,item) {
    $("<img/>").attr("src", item.media.m).appendTo("#images");
    if ( i == 3 ) return false;
  });
}

$('button').bind('click',function(){ //Triggers the ajax...
  if(cachedImageData[$('input').val()] === undefined){ //If this search doesn't exist...
    $.ajax({
      url:''
      data:{ tag: $('input').val() }, //Get the value however
      success: function(data){
        cachedImageData[$('input').val()] = data; //Save for later
        displayImages(data); //Run the display images function which is your $.each()
      }
    });
  }
});
发布评论

评论列表(0)

  1. 暂无评论