简体   繁体   中英

Navigate to another page after sending a long XMLHttpRequest

I have an XMLHttpRequest that insert a lot of data to a MySQL database and takes 5-10 seconds. Here's The code of the request:

function sendRequest(url, params, divToChange)
{
   // code for IE7+, Firefox, Chrome, Opera, Safari
   if (window.XMLHttpRequest)
   {
       var httpRequest = new XMLHttpRequest();
   }      
   else // code for IE6, IE5
   {
       var httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
   }

   // Stage 3 - open the request and prepare variables for the PHP method being  
      activated on server side//
   httpRequest.open("POST", url, true); 

   //Set request headers for POST command//
   httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
   httpRequest.setRequestHeader("Content-length", params.length);
   httpRequest.setRequestHeader("Connection", "close");

   httpRequest.onreadystatechange=function()
   {
       if(httpRequest.readyState==3)
       {     
           document.getElementById(divToChange).innerHTML='please wait';
       }
       if(httpRequest.readyState==4 && httpRequest.status==200)
       {
           document.getElementById(divToChange).innerHTML=httpRequest.responseText;
       }
   }

   httpRequest.send(params); // Stage 4 - sending the request to the server//

   //end when the server will responde we will execute the        
   "document.getElementById("txtHint").innerHTML=xmlhttp.responseText;" //

}

//Calling the request with this function//
function createEventList() 
{   

   var url = "grid-update_event_list.php";
   var params = "firstLoad=1";

   //Create the httpRequest and send it to the server//
   sendRequest(url,params, "eventsList");  
}

And this is defined in my html to get the responses text:

<p>Events List Status: <b id='eventsList'>  </b></p>

I cant understand 2 behaviors in my browser:

1- The "please wait" text never shows on the browser. When I've added an alert(httpRequest.readyState) to test what's happening, I got popup with "3" as expected, but I've seen that immediately after readyState==3 it goes to readyState==4 . It seems like they happen simultaneously. I do see the text returned in the httpRequest.responseText; of readyState==4 .

2- I cant navigate to another page after sending the request, The current page is responsive (I can change comboboxes) but when I try to navigate to another link the browser waits to readyState==4 and only then It continues to the link. I cant understand that either, because the request defined as asynchronous = true .

Am I doing something wrong that causing these 2 behaviors ? thanks.

1.- you need to understand the readystates of an ajax call. There are 5 different ready states. For more information look at this link:

ReadyStates

so you could use a different readystate ( i would use 1 or 2) to display the dialog at the beginning of the request. Otherwise just change the div BEFORE you send the httpRequest.

2.- Even if ajax calls are asyncronous, they are sequential. That is, if you send a request, you cannot send another request until you have received the response of that request. Changing pages is another request/response cycle, so you won't be able to change page until you have received the response of the first request.

Hope this helps...

I found this article and was really disappointed. I mean in the 21st Century how could an asynchronous background request block the whole browser for navigating? It just doesn't make sense, someone should have fixed this by now.

Well as it turns out, at least in my case, it's not the browser. The browser does have a limit to the number of concurrent requests, usually somewhere in the neighborhood of six. But that is there to prevent DoS attacks by malicious web pages. The REAL PROBLEM is PHP.

IF PHP uses the default file based session system, then the session is locked until it is closed either by the page exiting or by a call to session_write_close();

What is happening is the base page opens the session, does its thing and then closes, all nice and clean. Now the browser wants to AJAX something into a part of the page, and calls back to the same server that delivered the base page which reopens the session and holds it open until the AJAXing is done. In the mean time there is another section of the page that wants to dynamically load some content too from the same server with the same session. PHP says, "No, you have to wait. The session is already open by that other guy." As soon as the first AJAX closes the session the second one gets through and it does its thing. Now imagine that the first call takes 15 minutes. The second call and any link-clicks to that same server using the same session is going to be blocked until all the loads and clicks and stuff that came before it are finished. Nightmare! It makes it look like your page is frozen and your AJAX calls are being performed sequentially. Well they are, but not because of the browser or because of XmlHttpRequest.

How do we fix this? The simple way is to hit and run. If your page doesn't need to read or write into the session past the first few lines of code, then once you get the data out, call session_write_close(). That will unlock the session and the other guy can use it. I'm speculating on this next part but I think it will work. If you need to write into the session later, rather than holding it open, close it so that others can use it, then save your session ID and reopen it later with session_start($id).

The harder way is to write your own session handler that doesn't lock. This is actually what I did. I have a Cassandra based session handler that does not lock. The down side is that I'm subject to "Last in wins" concurrency, but in my case only my base pages actually write into the session, my AJAX calls don't write anything in so it is not a problem. Can't clobber your data if you don't have a hammer.

Hope this helps, because while the original answer was helpful in fixing my problem, it is a complete misunderstanding of what is actually going on. Asynchronous XmlHttpRequests are not sequential.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM