#657 bug
Juergen Naeckel

Recycling of an Ajax.Request object doesn't work as expected

Reported by Juergen Naeckel | April 22nd, 2009 @ 01:53 AM

I used prototype to pull search suggestions while the user enters his/her search criteria from the backend. The original code looked like that:


function doServerQuery(searchTerm)
{
  if(searchReq==undefined){
      searchReq = new Ajax.Request(searchSuggestURL, {
          method : "get",
          parameters : "q=" + encodeURI(searchTerm),
          onComplete: function(response){
            handleSearchSuggest(response.responseText);
          }
      });
  }
  else
  {
      searchReq.options.parameters = "q=" + encodeURI(searchTerm);
      searchReq.request(searchSuggestURL);
  }
}

Just provide some new search parameter and get going. Nope.
The issue lies in the recycling of the searchReq object. The constructor of the Request object processes the argument “parameters”. That does not happen when you just call the method “request”. Hence, you got to do it manually upfront. The string has to be converted using the method “toQueryParams”. Without this you will get an error 401: URI too long.
Next, the Ajax object internally maintains a flag “complete”. There are several states for the Request: 'Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'. When the status reaches “Complete” the Ajax object calls all registered onComplete listeners and informs them that the Ajax request is complete and passes the response to the listener. Once all listeners are notified the internal flag “complete” is set to true in order to mark the object basically as completely idle now. With that flag set, no more listener will be called.
Unfortunately when calling the method “request” you would assume that this flag gets reset. Well, it does not. You had to reset it manually upfront otherwise your handler will never be called.
So here is the working code.

{
  if(searchReq==undefined){
      searchReq = new Ajax.Request(searchSuggestURL, {
          method : "get",
          parameters : "q=" + encodeURI(searchTerm),
          onComplete: function(response){
            handleSearchSuggest(response.responseText);
          }
      });
  }
  else
  {
      searchReq._complete = false;
      searchReq.options.parameters = ( "q=" + encodeURI(searchTerm) ).toQueryParams();
      searchReq.request(searchSuggestURL);
  }
}

My suggestion:
change the method "request".
set_complete there to false.
check if the options.parameters of type string is. If so, call the method toQueryPrams first before further processing.
The current implementation is not intuitive and understandable (especially considering that variables with a leading underscore should be private and not set from the outside!).

Comments and changes to this ticket

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

The Prototype JavaScript library.

Shared Ticket Bins

People watching this ticket

Pages