Solved

Reset AJAX Requests

Posted on 2006-06-30
8
1,337 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
 
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
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

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Printing to a specific printer tray (HP 806dn printer) 3 62
jQuery animation faster 1 16
Phone Dialer 5 36
Asp.net mvc 5 5 16
Today I would like to talk about localizing (Internationalization) JavaScript applications. Introduction When creating an application that is going to be used by many people around the globe, it is important to remember that not everyone speak…
In my daily work (mainly using ASP.net), I need to write a lot of JavaScript code. One of the most repetitive tasks I do are the jQuery Ajax calls. You know: (CODE) I don't know if for you it's the same, but for me is soooo tedious to write the …
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…

708 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

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now