Search code examples
javascriptjqueryajaxeachgetjson

jQuery - Maintain Order of .each() while using .getJSON


I have a working function that checks for any input with a specific class name, then runs a getJSON call for each input's value:

function getTopFeeds() {
  if (jQuery('input.class-name').length > 0) {
    jQuery.each(jQuery('input.class-name'),function(){
      var feedName = jQuery(this).val();
      jQuery.getJSON("https://api.url/"+feedName).success(function(data) {
        if (!(data)) {
           return;
        }
        var result = data.results[0];
        if (result) {
            // Here I create HTML list items to display API data
        }
      });
    });
  }
}

It works, but because it's asynchronous it's not returning in the order the inputs on the page. How can I modify my existing function so that the data is displayed in the same order of the inputs?


Solution

  • If you want to wait until they've all come back, you can keep the results in an array and remember how many results you've seen; when you've seen as many results as requests, you're done. See comments:

    function getTopFeeds() {
        if (jQuery('input.class-name').length > 0) {
            // Get the inputs
            var inputs = jQuery('input.class-name');
            // Storage for the results
            var results = [];
            // Counter for # of responses we've seen
            var counter = 0;
            // Get them
            inputs.each(function(index) {
                var feedName = this.value;
                jQuery.getJSON("https://api.url/" + feedName)
                    .done(function(data) {
                        // Got a response, save it or null if falsy (would that really happen?)
                        results[index] = data ? data.results[0] : null;
                    })
                    .fail(function() {
                        // Error response, use null as a flag
                        results[index] = null;
                    })
                    .always(function() {
                        // Called after `done` and `fail` -- see if we're done
                        if (++counter === inputs.length) {
                            // Yes, we're done -- use the results in `results`
                            // Note that there will be `null`s for any that
                            // didn't have data
                        }
                    });
            });
        }
    }