Hi list,
In our framework, we are using partial ajax requests to validate input field as soon as the user leaves the text field.
In a very complex form, we noticed that the response time of the partial requests depends on the position of the input field. The validation logic is encapsulated in InputFieldComponent, and the form component is mainly a WORepetition of these
InputFieldComponents.
The range of the measured response times is something between 60 ms for the first component and 1200 ms for the last component in the form. The longest response time is about the same as I would do a normal form submit.
Did anybody noticed a similar phenomena?
Anyway, my questions are:
1. Why does the position of a field make a difference at all?
2. Is there a possibility to speed up things?
Here my observations:
A profiling session reveals, that a lot of time is spent in takeFormValuesFromRequest and invokeAction.
Answer for #1: As soon as ajaxSubmitButton which triggered the request is found, invokeAction is somehow "interrupted". (see ERXAjaxContext.wasFormSubmitted...)
As it is possible to eliminate unnecessary component tree traversal after the right ajaxSubmitButton.action is found, it should also be possible to ignore the other irrelevant childComponents.
ASSUMPTION:
a) for partial submits, we get only one form value (i.e the partialFormSenderID).
b) the partialFormSenderID is the path of the sender component in the overall component hierarchy.
IDEA: for the component hierarchy tree traversal, we may ignore child components not on the path to the partialFormSender.
Solution (proof of concept) for #2: In ERXWORepetition, I changed takeFormValuesFromRequest and invokeAction as follows:
public
void takeValuesFromRequest(WORequest
worequest, WOContext
wocontext) {
WOComponent
wocomponent = wocontext.component();
String
partialFormSenderID = ERXAjaxApplication.partialFormSenderID(worequest);
Context
context = createContext(wocomponent);
int
count = _count(context,
wocomponent);
boolean
checkHashCodes = checkHashCodes(wocomponent);
for (int
index = 0;
index < count;
index++) {
_prepareForIterationWithIndex(context,
index, wocontext,
wocomponent, checkHashCodes);
if(partialFormSenderID
== null ||
partialFormSenderID.startsWith(wocontext.elementID())) { // NO RECURSION if component[index]
does not match senderID
super.takeValuesFromRequest(worequest,
wocontext);
}
}
if (count > 0) {
_cleanupAfterIteration(count,
wocontext,
wocomponent);
}
}
invokeAction is patched in similar way.
The result is, that the ajax request at the bottom of the page takes now 60 ms instead of 1200ms :-)
Unfortunately, this is not a general solution. There are scenarios, there invokeAction will not invoke any actions at all :-(
Has anybody an idea for a general solution? Maybe a completely different approach?
Best regards (and sorry for this long post)
|