Async AJAX requests in each loop

I got the problem with async ajax requests which are called in WordPress plugin.

Here’s the code I want to utilise (read from the bottom):

Read More
var $ = jQuery.noConflict();

/*
* jQuery.ajaxQueue - A queue for ajax requests
* 
* (c) 2011 Corey Frang
* Dual licensed under the MIT and GPL licenses.
*
* Requires jQuery 1.5+
*/ 
(function($) {

// jQuery on an empty object, we are going to use this as our Queue
var ajaxQueue = $({});

$.ajaxQueue = function( ajaxOpts ) {
var jqXHR,
    dfd = $.Deferred(),
    promise = dfd.promise();

// queue our ajax request
ajaxQueue.queue( doRequest );

// add the abort method
promise.abort = function( statusText ) {

    // proxy abort to the jqXHR if it is active
    if ( jqXHR ) {
        return jqXHR.abort( statusText );
    }

    // if there wasn't already a jqXHR we need to remove from queue
    var queue = ajaxQueue.queue(),
        index = $.inArray( doRequest, queue );

    if ( index > -1 ) {
        queue.splice( index, 1 );
    }

    // and then reject the deferred
    dfd.rejectWith( ajaxOpts.context || ajaxOpts,
        [ promise, statusText, "" ] );

    return promise;
};

// run the actual query
function doRequest( next ) {
    jqXHR = $.ajax( ajaxOpts )
        .done( dfd.resolve )
        .fail( dfd.reject )
        .then( next, next );
}

return promise;
};

})(jQuery);

function add_log( log ) {

var $textarea = $('#log');
var content = $textarea.val();

$textarea.val( content + log + "n" ); 
$textarea.scrollTop( $textarea[0].scrollHeight );

}

function process_post(post_id, post_title) {

return $.ajaxQueue({
	type: 'POST',
	async: true,
	url: ajaxurl,
	data: {
		'action': 'process_post',
		'nonce': $('input#steps').val(),
		'post': post_id
	},
	success: function(response) {

    	if ( response.success == false ) {
    		add_log('Processing post: ' + post_title + ' failed. Please restore the database backup.' );
    		throw new Error();
    	}

    	add_log('Post: ' + post_title + ' processed successfully' );

    }
}); // ajax post

}

function process_posts(post_type) {

// processing posts each
	
return $.ajaxQueue({
	type: 'POST',
	async: true,
	url: ajaxurl,
	data: {
		'action': 'get_posts',
		'nonce': $('input#steps').val(),
		'post_type': post_type
	},
	success: function(response) {

    	if ( response.success == false ) {
    		return false;
    	}

    	var $posts = response.data;
    	add_log("n" + '# Posts loaded and ready to convert');

    	$.each($posts, function( post_id, post_title ) {
			process_post(post_id, post_title);
    	}); // each post

    }
}); // ajax posts

}

function process_term( term_id, term_title ) {

$.ajaxQueue({
	type: 'POST',
	async: true,
	url: ajaxurl,
	data: {
		'action': 'process_term',
		'nonce': $('input#steps').val(),
		'term': term_id
	},
	success: function(response) {

    	if ( response.success == false ) {
    		add_log('Processing term: ' + term_title + ' failed. Please restore the database backup.' );
    		throw new Error();
    	}

    	add_log('Term: ' + term_title + ' processed successfully' );

    }
});

}

function get_terms( taxonomy ) {

$.ajaxQueue({
	type: 'POST',
	async: true,
	url: ajaxurl,
	data: {
		'action': 'get_terms',
		'nonce': $('input#steps').val(),
		'taxonomy': taxonomy
	},
	success: function(response) {

    	if ( response.success == false ) {
    		throw new Error();
    	}

    	var $terms = response.data;

    	if ( $.isEmptyObject($terms) ) {
    		add_log('# Taxonomy: ' + taxonomy + ' has no terms - skipping' );
    	} else {

    		add_log('# Terms loaded and ready to convert');

    		$.each($terms, function( term_id, term_title ) {
    			process_term( term_id, term_title );
    		}); // each terms

    	} // endif

    }

});

}

function process_taxonomies( taxonomies ) {

// processing taxonomies
	
$.each(taxonomies, function( taxonomy ) {

	add_log("n" + '## Processing taxonomy: ' + taxonomy);

	get_terms( taxonomy );

}); // each taxonomy

}

function process( $data ) {

// processing each post type
$.each($data, function( post_type, taxonomies ) {

	add_log( "n" + '## Processing post type: ' + post_type);

	process_taxonomies( taxonomies );
    process_posts( post_type );

}); // each post type

}

What it should do – it should asynchronously process wp taxonomies and posts. Steps:

  1. Take each post type and process taxonomies and posts
  2. Take each taxonomy and get terms for it (ajax)
  3. Process each term (ajax)
  4. Get posts (ajax)
  5. Process each post (ajax)

At any step it should save a log in the textarea.

Instead of nice synchronous log I got everything mixed (because of async ajax). Changing ajax async to false results in blank textarea and at the end of the process it’s adding all log messages at once which is not what I’m looking for.

As you can see I’m already using ajaxQueue but it doesn’t help. Also playing with Deffered and when() desn’t do the job.

Here’s the example log:

## Processing post type: post

## Processing taxonomy: category
# Terms loaded and ready to convert

## Processing taxonomy: post_tag

## Processing post type: testomonial
Term: Uncategorized processed successfully
Term: Category processed successfully
# Terms loaded and ready to convert

# Posts loaded and ready to convert

# Posts loaded and ready to convert
Term: Tag processed successfully
Term: Tagen processed successfully
Post: Hello processed successfully
Post: German only title processed successfully
Post: English only title processed successfully
Post: Mixed title EN processed successfully
Post: Gutentag processed successfully
Post: Testimonial 1 processed successfully
Post: Testimonial 2 processed successfully
Post: Testimonial 3 processed successfully

I’ll be very grateful for any suggestion.

Related posts