Multiple JSON calls on same click event [Solved]

Hi all,

I have a click event which displays details of an item from a JSON source, I also have another call for more JSON displaying related items, both within the same click event.

The problem is sometimes, not always I need two clicks for the second JSON call to display (related items). I’m wondering how I can insure/guarantee when the items display, both JSON results will be shown on first click.

Code

$(document).on('click', '.more', function(e){
    ....
  
    var json_item       = "//example.com/search.json?..";
    var related_items   = "//example.com/search.json?..";

    // details
    $.getJSON(json_item, function(data) {
      $.extend(data, renderFuncs);
      
      var templateB = $('#itemTemplate').html();
      var htmlB = Mustache.render(templateB, data);

      $('#item').html(htmlB);
    });
      
    // related
    $.getJSON(related_items, function(data) {
      $.extend(data, renderFuncs);
      
      var templateX = $('#relatedTemplate').html();
      var htmlX = Mustache.render(templateX, data);

      $('#related').html(htmlX);
    });
  
    e.preventDefault();
});

html

<a href="#" class="more">More</a>
<div id="item"></div>
<div id="related"></div>

After reading lots of information, I stumbled upon jQuery .when and .then is this the best way?
Something about promises?

Any suggestions / examples, thanks.

I could even introduce a third JSON call moving forward.

Barry

Probably the easiest way is to chain both calls together with a then():

$(document).on('click', '.more', function(e){
  ....

  var json_item       = "//example.com/search.json?..";
  var related_items   = "//example.com/search.json?..";

  // details
  $.getJSON(json_item, function(data) {
    $.extend(data, renderFuncs);

    var templateB = $('#itemTemplate').html();
    var htmlB = Mustache.render(templateB, data);

    $('#item').html(htmlB);
  }).then(
    // related
    $.getJSON(related_items, function(data) {
      $.extend(data, renderFuncs);

      var templateX = $('#relatedTemplate').html();
      var htmlX = Mustache.render(templateX, data);

      $('#related').html(htmlX);
    });
  );

  e.preventDefault();
});

This will ensure they are carried out sequentially.

Or, as $.getJSON returns a Promise, you can use Promise.all to do something when the Promises resolve:


$(document).on('click', '.more', function(e){
    ....

    var json_item       = $.getJSON("//example.com/search.json?..");
    var related_items   = $.getJSON("//example.com/search.json?..");

    Promise.all([json_item, related_items]).then(function(data){
      // Both promises done!
      // Do something with data
    });

    e.preventDefault();
});

Thanks @James_Hibbard

So I could potentially do something like:

$(document).on('click', '.more', function(e){
    ....
  
    var json_item       = "//example.com/search.json?..";
    var related_items   = "//example.com/search.json?..";

    Promise.all([json_item, related_items]).then(function(data){

      $.extend(data, renderFuncs);

      var templateB = $('#itemTemplate').html();
      var htmlB = Mustache.render(templateB, data);
      $('#item').html(htmlB);

      var templateX = $('#relatedTemplate').html();
      var htmlX = Mustache.render(templateX, data);
      $('#related').html(htmlX);

      });

e.preventDefault();
});

I see all we add in the first snippet is .then
So why would we use or what are the benefits of using one of the other .then vs Promise.all ?

And is there a way to limit the amount of items returned for the related items?
Thanks for the links just reading on promises now.

Barry

Not quite. Don’t forget the call to $.getJSON:

var json_item       = $.getJSON("//example.com/search.json?..");
var related_items   = $.getJSON("//example.com/search.json?..");

With Promise.all, the requests will all get fired off at once, then when the final one resolves, the callback will execute. Using .then() the requests will fire one after another.

Query string parameter?

If you add more requests, you might also like to move the template manipulation into its own function:

function processTemplate(selector, data){
  var template = $(selector + 'Template').html();
  return = Mustache.render(template, data);
  $(selector).html(html);
}

$(document).on('click', '.more', function(e){
  ....
  
  var json_item       = $.getJSON("//example.com/search.json?..");
  var related_items   = $.getJSON("//example.com/search.json?..");

  Promise.all([json_item, related_items]).then(function(data){
    $.extend(data, renderFuncs);
    processTemplate('#item', data[0]);
    processTemplate('#related', data[1]);
  });

  e.preventDefault();
});
2 Likes

Well spotted, so we are generally just wrapping the promise all around the calls, if thats correct?

$(document).on('click', '.more', function(e){
    ....
  
    var json_item       = "//example.com/search.json?..";
    var related_items   = "//example.com/search.json?..";

    Promise.all([json_item, related_items]).then(function(data){

      $.getJSON(json_item, function(data) {
        $.extend(data, renderFuncs);

        var templateB = $('#itemTemplate').html();
        var htmlB = Mustache.render(templateB, data);
        $('#item').html(htmlB);
      });

      $.getJSON(related_items, function(data) {
        $.extend(data, renderFuncs);

        var templateX = $('#relatedTemplate').html();
        var htmlX = Mustache.render(templateX, data);
        $('#related').html(htmlX);
      });

    });
});

And is it possible to combine the two getJSON calls like you have done with the Promise.all ?
$.getJSON(json_item, related_items, function(data) {}

So the benefit of using .then means we don’t have to wait for everything to be fully loaded. But if we use Promise.all nothing will show until everything is available. Is that right?

Cool, just seen your latest post thanks, taking shape :slight_smile:

I’ll run some further testing lots of useful information, thanks.

Barry

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.