0

I am writing a jQuery plugin which takes in an array of json files that I then need to compile into one big array.

So far the different parts of the code has work on it's own but once I put it together I am not able to return the new array.

I am assuming it is either me not understanding how to return values from the nested loops or an issue that the $.get() is Asynchronous and the $.each() loops are synchronous. Or likely a mix of both.

I've tried with jQuery $.Deferred but no luck. Any pointers on how to solve this is mostly welcoming.

Here is the plugin code as of now. I've commented the code so it should be 'easy' to see what I am trying to do:

(function ( $ ) {
 
    $.fn.presspull = function( options ) {
 
        // This is the defaults settings which can be changed via the plugin call.
        var settings = $.extend({
            // These are the defaults.
            template :  Handlebars.compile( $('#pressTemplate').html() ),
            placeHolder :  $("#press-grid"),
            addMoreBtn :  $("a#press-show-more"),
            segment  :  4,
            dataSource  :  []
             
        }, options ); // end settings

        // non mutable elements which can not be changed from the plugin call.
        var cache = {
          pressArray : new Array(),
          compileCount: 0,
          segmentItt : 0
        }; // end cache

/*============================================================================
  – Compile Source: function to build and sort the combined press.
==============================================================================*/

        function compileSource() {
         // check if the data source contains anything.
         if ( settings.dataSource.length > 0 ) { 
          // for each json file in the data source do...
          $.each( settings.dataSource , function( k, v ) {
           // get the data 
           $.get( v, function( data, status, xhr ){
            // next loop through the output
            $.each( data, function( i, e ){
             // add each entry to the pressArray
             cache.pressArray.push( e );
            }); // end each
           // once done do..
           }).done( function() {
            // compile count increments for every data source
      cache.compileCount ++;
      if ( cache.compileCount == settings.dataSource.length ) { 

       cache.pressArray.sort( function( a, b ) {
        var c = new Date(a.date),
         d = new Date(b.date);
     
        return c>d ? -1 : c<d ? 1 : 0;
       }); // end sort

       // after compiling and sorting the new list we return it.

      }; // end if
     // if there is a failure in getting the data it's logged as following        
           }).fail( function() {
         console.log("Failed to get data from: " + v );
       }); // end get.done
          }); // end each
         } else {
          console.log("Source files not found!");
         };

         return console.log( cache.pressArray);
        }; // end compileSource

 
    }; // end $.fn.presspull
 
}( jQuery ));

The json files looks as following:

[
      {
            "publication": "Dazed & Confused",
            "date": "2013-05-01",
            "region": "UK",
            "cover": "{{ 'img-press-cover-dazed-2013.png' | asset_url }}",
            "pressmedia": [
                  {
                  "name":"soma",
                  "image": "Document Name 1 - General",
                  "description": "description for image 1",
                  "keyproduct": "link to the key product on the image"
                  },
                  {
                  "name":"soma2222",
                  "image": "Document Name 2 - General",
                  "description": "description for image 1",
                  "keyproduct": "link to the key product on the image"
                  }

            ]

]

And the plugin is called as following:

$().presspull({
      dataSource   :   [
      "http://link/to/external/json/file/01",
      "http://link/to/external/json/file/02",
      "http://link/to/external/json/file/03"
      ]
});
  • 2
    To begin with, after the `function compileSource()` function u may add `compileSource()`. Second, u may use **callback**. – ch271828n Apr 06 '15 at 11:24
  • You can' return value from `compileSource` as it is asynchronous.... you need to use a callback to process the combined result – Arun P Johny Apr 06 '15 at 11:27
  • @Turtle - thank you for the comment. I thought the use of .done() was the callback by using the Promise interface? – Sofus Graae Apr 06 '15 at 11:29
  • @ArunPJohny - Thank you for the comment - I might be misunderstanding you but I was under the impression the use of .done() was the callback. If not would you mind pointing me in the direction of where the callback should be added? – Sofus Graae Apr 06 '15 at 11:40
  • @SofusGraae http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call – Arun P Johny Apr 06 '15 at 11:44
  • @SofusGraae something like http://jsfiddle.net/arunpjohny/y0w62u3z/1/ – Arun P Johny Apr 06 '15 at 11:45
  • @ArunPJohny - Argh I see what you mean now, your example makes perfect sense and Thank you so much for the fiddle. Can you add it as an answer so I can mark it solved? – Sofus Graae Apr 06 '15 at 12:08

1 Answers1

1

The problem here is your method compileSource is asynchronous which means when you try to return array from the method you ajax contents would not have completed so you will get an empty array.

The solution is to use a callback

    function compileSource(callback) {
        // check if the data source contains anything.
        if ( settings.dataSource.length > 0 ) { 
            // for each json file in the data source do...
            $.each( settings.dataSource , function( k, v ) {
                // get the data 
                $.get( v, function( data, status, xhr ){
                    // next loop through the output
                    $.each( data, function( i, e ){
                        // add each entry to the pressArray
                        cache.pressArray.push( e );
                    }); // end each
                // once done do..
                }).done( function() {
                    // compile count increments for every data source
                    cache.compileCount ++;
                    if ( cache.compileCount == settings.dataSource.length ) { 

                        cache.pressArray.sort( function( a, b ) {
                            var c = new Date(a.date),
                                d = new Date(b.date);

                            return c>d ? -1 : c<d ? 1 : 0;
                        }); // end sort

                        callback(cache.pressArray)

                        // after compiling and sorting the new list we return it.

                    }; // end if
                // if there is a failure in getting the data it's logged as following               
                }).fail( function() {
                    console.log("Failed to get data from: " + v );
                }); // end get.done
            }); // end each
        } else {
            console.log("Source files not found!");
        };
    }; // end compileSource

    //call the compile method
    compileSource(function(array){
        //this function will be called once all the data is received and sorted, the sorted array will be passed as an argument
    })
Community
  • 1
  • 1
Arun P Johny
  • 384,651
  • 66
  • 527
  • 531