Support

Account

Home Forums Backend Issues (wp-admin) Unnecessary AJAX-calls

Solving

Unnecessary AJAX-calls

  • I have a serious performance problem in admin while editing pages. And it seems to boil down to how ACF handles AJAX.

    An example: I have a relationship field:

    {
                  "key":"field_54539b8b34e8e",
                  "label":"Imported Callouts",
                  "name":"automatic",
                  "prefix":"",
                  "type":"relationship",
                  "instructions":"Choose a post, page or custom post to display it as a callout. The callout will use the callout excerpt and featured image of the target article, if those are not present it will simply not display.",
                  "required":0,
                  "conditional_logic":[
                    [
                      {
                        "field":"field_54539b8b34ad6",
                        "operator":"==",
                        "value":"automatic"
                      }
                    ]
                  ],
                  "wrapper":{
                    "width":"",
                    "class":"",
                    "id":""
                  },
                  "post_type":[
                    "post",
                    "page",
                    "accessories"
                  ],
                  "taxonomy":"",
                  "filters":[
                    "search",
                    "post_type",
                    "taxonomy"
                  ],
                  "elements":[
                    "featured_image"
                  ],
                  "max":4,
                  "return_format":"object"
                }

    This field resides in a acf-layout with some conditional logic. This logic is basically grouping of fields to enable choosing the next page block:

    "choices":{
                    "null":"Select content type",
                    "content":"Standard content block",
                    "feature":"Content block with aligned image",
                    "columns":"Callout\/feature columns with images and text",
                    "modal_media":"Youtube or Soundcloud clips that load in a modal popup",
                    "manual":"Manually created callouts",
                    "automatic":"Automatic article callouts",
                    "specification_lists":"Specification list",
                    "faq":"FAQ",
                    "files":"Downloadable files",
                    "youtube":"Youtube movie or playlist",
                    "soundcloud":"Soundcloud clip or playlist",
                    "gallery":"Gallery or slideshow",
                    "imagemap":"Imagemap"
                  },

    Even though the current page I edit doesn’t make use of the relationship field (automatic article callouts), ACF makes the AJAX call to populate it.

    That would be OK if it did it once. But on the “worst” page I have there is a total of 14 body layouts, and therefore some 14 AJAX calls for the same relationship. A relationship that isn’t even used on the page in question.

    That takes almost 20 seconds to handle, which is not so OK when the loading time of the editing screen is about a minute or more.

    I’ve added a screen shot of the chrome timeline for those calls. They start in series, load concurrently, but all responses from the server not related to those calls waits for them to finish.

    And that is just setting up for editing. When I press save the fecal matter really hits the fan. Loading I only get what is already there, but when saving the post.php only takes something like 30 seconds to compute. On top of that I get whatever oEmbeds that needs caching and the 20 seconds for the relation-fields.

    In total I have a time from pressing save to a responsive edit page in the order of close to two minutes. Enough time for most Chrome or FF installations to start complaining about an unresponsive page.

    Getting oEmbed timeouts on top of that is enough to kill the site dead, the worst case so far was 51 misses on the oEmbed calls. That, funnily enough was for mostly unpopulated and inactive oEmbed-fields and four wysiwyg soundcloud embeds.

    So what do I want?

    If something is hidden by conditional logic, the intuitive result is for it not to load at all. No AJAX, no population while inactive, no computations on save.

    Basically only save and handle what is actually there.

    Also: If a field has already made an AJAX-call, why not use that rather than make another identical call.

    Thirdly: Is it a wordpress bug that the whole bloody thing stalls while waiting for the relations AJAX? Shouldn’t the AJAX be async, continuing with the rest of the page and then populate the field on response?

    Something is fishy here.

  • Damn, I should have taken a closer look at how ACF handles conditionals. I had the impression it loaded just what was needed, not everything. But it seems that with conditionals all the fields are still there, just hidden.

    This of course means that some calls are made for fields I don’t use. And some scripts runs brutally slow.

    I chose conditionals, because it made the interface behave as I wanted it to. But what I should have done where to create new layouts for each content type, since those load as needed rather than always.

    As soon as I moved the relationship field to its own layout, the AJAX-calls stopped. I then found the next bottleneck, which where the wysiwygs. I have a 40 second latency between loading tinymce and rendering/continuing.

    It seems the code for handling conditionally hidden elements is less than complete. Really, stuff should be truly inactive when they are conditionally hidden. It’s bad enough that they get posted, they should not be scripted as well.

    But, to be fair, it makes a kind of sense – if you see conditionals not as a way of choosing what kind of content to add, but as a way to make variations in the kind you have already chosen.

    Could I ask, as a minimum, that this is reflected in the documentation? It would prevent the kind of gotchas I’m experiencing now. I’m among those that tend to RTFM before I start, so it would have been a great help avoiding this situation.

  • Semi-related – I’ve got a page with a repeatable field that the client has created ~150 repeated fields with.

    On some browsers this causes the page to become unresponsive. I say semi-related because it looks to be due to the get_visibility() js method for fields with conditional logic.

    Attached is the js profile. If I remove all field conditional rules, or force get_visibility() to return true, then the page does not become unresponsive.

  • I’ve come up with a rudimentary patch to input.js that solves the excessive $.each() and $el.closest() calls when there is an excessive amount of repeatables.

    changing this:

    		get_visibility : function( $target, rule ){
    			
    			//console.log( 'conditional_logic.get_visibility(%o, %o)', $target, rule );
    			
    			// update cache (cache is cleared after render_fields)
    			if( !acf.isset(this.cache, rule.field) ) {
    				
    				//console.log('get_fields(%o)', rule.field);
    				
    				// get all fields for this field_key and store in cache
    				this.cache[ rule.field ] = acf.get_fields(rule.field, false, true);
    				
    			}
    			
    			
    			// vars
    			var $triggers = this.cache[ rule.field ],
    				$trigger = null;
    			
    			
    			// bail early if no triggers found
    			if( !$triggers.exists() ) {
    				
    				return false;
    				
    			}
    			
    			
    			// set $trigger
    			$trigger = $triggers.first();
    			
    			
    			// find better $trigger
    			if( $triggers.length > 1 ) {
    				
    				$triggers.each(function(){
    					
    					// vars
    					$parent = $(this).parent();
    					
    					
    					if( $target.closest( $parent ).exists() ) {
    						
    						$trigger = $(this);
    						return false;
    					}
    
    				});
    				
    			}
    			
    			
    			// calculate
    			var visibility = this.calculate( rule, $trigger, $target );
    			
    			
    			// return
    			return visibility;
    		},

    To this:

    		get_visibility : function( $target, rule ){
    			
    			//console.log( 'conditional_logic.get_visibility(%o, %o)', $target, rule );
    			
    			// update cache (cache is cleared after render_fields)
    			if( !acf.isset(this.cache, rule.field) ) {
    				
    				//console.log('get_fields(%o)', rule.field);
    				
    				// get all fields for this field_key and store in cache
    				this.cache[ rule.field ] = acf.get_fields(rule.field, false, true);
    				
    			}
    			
    			
    			// vars
    			var $triggers = this.cache[ rule.field ],
    /*change*/		$trigger  = $target.closest('.acf-row').find('tr.field_key-'+rule.field);
    			
    			
    			// bail early if no triggers found
    			if( !$triggers.exists() ) {
    				
    				return false;
    				
    			}
    /*change*/	else if ( !$trigger.exists() ) {			
    			
    				// set $trigger
    				$trigger = $triggers.first();
    				
    				
    				// find better $trigger
    				if( $triggers.length > 1 ) {
    					
    					$triggers.each(function(){
    						
    						// vars
    						$parent = $(this).parent();
    						
    						
    						if( $target.closest( $parent ).exists() ) {
    							
    							$trigger = $(this);
    							return false;
    						}
    
    					});
    					
    				}
    
    			}
    			
    			
    			// calculate
    			var visibility = this.calculate( rule, $trigger, $target );
    			
    			
    			// return
    			return visibility;
    		}
Viewing 4 posts - 1 through 4 (of 4 total)

The topic ‘Unnecessary AJAX-calls’ is closed to new replies.