Return 来自嵌套循环中的 $.get() 的数组

Return array from $.get() in nested loops

我正在编写一个 jQuery 插件,它接收一个 json 文件数组,然后我需要将这些文件编译成一个大数组。

到目前为止,代码的不同部分都是独立工作的,但是一旦我将它们放在一起,我就无法 return 新数组。

我假设要么是我不理解如何从嵌套循环中 return 值,要么是 $.get() 是 Asynchronous 和$.each() 循环是 同步的 。或者可能是两者的结合。

我试过 jQuery $.Deferred 但没有成功。任何关于如何解决这个问题的建议都很受欢迎。

这是目前的插件代码。我已经对代码进行了评论,所以应该 'easy' 看看我想做什么:

(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 ));

json 文件如下所示:

[
      {
            "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"
                  }

            ]

]

插件调用如下:

$().presspull({
      dataSource   :   [
      "http://link/to/external/json/file/01",
      "http://link/to/external/json/file/02",
      "http://link/to/external/json/file/03"
      ]
});

这里的问题是你的方法 compileSource 是异步的,这意味着当你尝试从方法 return 数组时你 ajax 内容不会完成所以你会得到一个空的数组。

解决方法是使用回调

    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
    })
  • How do I return the response from an asynchronous call?