在嵌套循环中从$ .get()返回数组

时间:2015-04-06 11:20:29

标签: javascript jquery json asynchronous

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

到目前为止,代码的不同部分都有自己的工作,但是一旦我把它放在一起,我就无法返回新的数组。

我假设要么我不理解如何从嵌套循环中返回值,要么$ .get()是 Asynchronous 并且$ .each()循环是同步。或者两者兼而有之。

我尝试过使用jQuery $ .Deferred但没有运气。关于如何解决这个问题的任何指示都非常欢迎。

这是截至目前的插件代码。我已经对代码进行了评论,因此我应该很容易看到我想要做的事情:

(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"
      ]
});

1 个答案:

答案 0 :(得分:1)

这里的问题是你的方法compileSource是异步的,这意味着当你尝试从方法中返回数组时,你的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
    })