Solved

Reset AJAX Requests

Posted on 2006-06-30
8
1,339 Views
Last Modified: 2012-05-05
I'm building a simple AJAX search field for a buy/sell tickets website I've been developing for a client. Users can enter city, state, venue, artist, and event date in the search field. As they type it behaves very much like Google Suggest, giving recommedations for what they're typing. When they're finished typing, after waiting for a second or two, it will send the data and update the <div> on the right with search results.

The problem that I'm coming across is that if I try to change too many fields at once (keep in mind, each one may call an AJAX request), it gets confused, or overflows, or blows up, or something--in any case the AJAX requests just stop working. It works perfectly as long as I don't try to move too fast. Ideally, I'd like to prevent this altogether, so that it *always* works, but if that's not really plausible, then I'd at least like a "Search" button users can press that will forcibly reset all AJAX requests, and then send whatever data's been entered. I tried to implement this already, but it doesn't seem to work.

To create the XMLHttpRequest object, I used this code that I found in "Rasmus' 30-second AJAX tutorial":
    function createRequestObject()
    {
        var ro;
        if ( navigator.appName == 'Microsoft Internet Explorer' )
        {
            ro = new ActiveXObject('Microsoft.XMLHTTP');
        }
        else
        {
            ro = new XMLHttpRequest();
        }
        return ro;
    }
    var http = createRequestObject();

And on the "Search" button, like I said, I tried to add some code that would force it to absolutely reset all requests, but it's not working--if you update the fields too fast, it freezes up, and this code isn't enough to unfreeze it.
    function clearAndSearch()
    {
        try
        {
            http.abort();
        }
        catch (e)
        {
            http = createRequestObject();
        }
        doSearch();
        return;
    }

I can send you a link to a working example of what I've got if you'd like to see it, but I can assure you that there's *a lot* of code, so I don't know if you really want to sift through all of it.
0
Comment
Question by:soapergem
  • 4
  • 4
8 Comments
 
LVL 15

Expert Comment

by:bpmurray
ID: 17023281
Your create doesn't look very solid. I'd do something like:

         if (window.XMLHttpRequest) {
              try {
                  ro = new XMLHttpRequest();
               } catch(e) {
                  alert( (e.message == undefined) ? e : e.message);
                  ro = null;
               }
         // Otherwise, try IE's ActiveX version
         } else if (window.ActiveXObject) {
            try {
               ro = new ActiveXObject("Msxml2.XMLHTTP");
            } catch(e) {
               try {
                  ro = new ActiveXObject("Microsoft.XMLHTTP");
               } catch(e) {
                  alert( (e.message == undefined) ? e : e.message);
                  ro = null;
               }
            }
         }

Are you using a different XMLHttpRequest object for each request? The problem is that you're firing off ASYNC requests using a single-threaded language. If you try to reuse the XHR before it's finished, you'll get the thing confused. Be very careful - if you use too much AJAX, it'll kill your servers and cause all sorts of odd behaviors in your client. Don't overdo it!
0
 
LVL 15

Expert Comment

by:bpmurray
ID: 17023332
Debugging AJAX can be difficult, but try doing it using Firefox withthe venkman debugger and firebug, both of which are extensions. Firebug allows you to look at XmlHettpRequests, so it's really useful.
0
 
LVL 6

Author Comment

by:soapergem
ID: 17024693
So are you suggesting I create more than one AJAX object for separate requests? Also, when I call this command a second time...

    http = createRequestObject();

...does that totally reinitialize that object?
0
ScreenConnect 6.0 Free Trial

Want empowering updates? You're in the right place! Discover new features in ScreenConnect 6.0, based on partner feedback, to keep you business operating smoothly and optimally (the way it should be). Explore all of the extras and enhancements for yourself!

 
LVL 15

Expert Comment

by:bpmurray
ID: 17024724
Yes, when you have multiple AJAX requests running that have not been cleaned up, you have to use a new one. Rather than creating too many, you should create one for each request type, so if you're using AJAX to fill three different listboxes, you should use three XHR objects:

http1 = createRequestObject();
http2 = createRequestObject();
http2 = createRequestObject();

It isn't clear to me if you create a new object, but you have to kill the previous use before you start a new request, so before making an AJAX call on any object, call http.abort() like you've done above. It's not clear from your description, but it seems that you only do this when Search is pressed, instead of each time. If there's a request outstanding on the XHR, i.e. if it hasn't responded yet, you MUST abort before launching a new request.
0
 
LVL 6

Author Comment

by:soapergem
ID: 17025221
Well, it actually calls requests much more frequently than just when you press the Search button. In fact, I've got onchange handlers every <select> box and an autosuggest feature for my three <input> boxes. If you do want to take a look, I've got it here:

http://www.streetcornertickets.com/new/template.html

Also, this is the function I'm using to send requests:

function ajax(action, method, handler, params)
{
      var uri = ( method == 'get' ) ? (action + '?' + params) : action;
      var data = null;
      
      http.open(method, uri);
      http.onreadystatechange = function()
      {
            if ( http.readyState == 4 && http.status == 200 )
            {
                  eval(handler + '();');      //      received data in http.responseText
            }
      }
      
      if ( method == 'post' )
      {
            data = params;
            http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
            http.setRequestHeader('Content-length', data.length);
            http.setRequestHeader('Connection', 'close');
      }
      
      http.send(data);
      return;
}
0
 
LVL 6

Author Comment

by:soapergem
ID: 17025227
I just had another idea, too. I could add a simple boolean variable to the global scope, like this:
var request_open = false;

And then with each request, set it to true, but set it back to false when a response is received. However, it would check if it's set to true before sending a request, and if so run the abort command first. Would that work?
0
 
LVL 15

Accepted Solution

by:
bpmurray earned 500 total points
ID: 17026273
After looking at the page, this shouldn't actually be an issue since each request should be finished before the next starts. I appreciate this may not always be the case, so you could try:

function ajax(action, method, handler, params)
{
     var uri = ( method == 'get' ) ? (action + '?' + params) : action;
     var data = null;
     
     http.abort();  // Just assume it's active & force it to terminate
     http.open(method, uri);
    ...

The idea is to systematically nuke the request, just in case - you don't need a boolean in this case since it happens every time. If you feel a need to include a conditional, you could do
   if (http.status != 0) {
      http.abort();
   }
0
 
LVL 6

Author Comment

by:soapergem
ID: 17026797
The first method worked like a charm--without the conditional. I think I do prefer having just a single request object; using http1, http2, http3, etc. just seems messy. Thanks so much for your help!
0

Featured Post

NAS Cloud Backup Strategies

This article explains backup scenarios when using network storage. We review the so-called “3-2-1 strategy” and summarize the methods you can use to send NAS data to the cloud

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
Boost your ability to deliver ambitious and competitive web apps by choosing the right JavaScript framework to best suit your project’s needs.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

832 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question