0

我有一个 XMLHttpRequest 将大量数据插入 MySQL 数据库,需要 5-10 秒。这是请求的代码:

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");  
}

这是在我的 html 中定义的以获取响应文本:

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

我无法理解浏览器中的两种行为:

1-“请稍候”文本永远不会显示在浏览器上。当我添加了一个alert(httpRequest.readyState)来测试正在发生的事情时,我得到了预期的“3”弹出窗口,但我在readyState==3它转到readyState==4. 似乎它们同时发生。我确实看到了在 of 中返回的httpRequest.responseText;文本readyState==4

2-发送请求后我无法导航到另一个页面,当前页面是响应式的(我可以更改组合框)但是当我尝试导航到另一个链接时,浏览器等待到 readyState==4,然后它才会继续链接。我也无法理解,因为请求定义为asynchronous = true.

我做错了什么导致这两种行为吗?谢谢。

4

2 回答 2

2

1.- 您需要了解 ajax 调用的就绪状态。有 5 种不同的就绪状态。有关更多信息,请查看此链接:

就绪状态

因此您可以使用不同的就绪状态(我会使用 1 或 2)在请求开始时显示对话框。否则,只需在发送 httpRequest 之前更改 div。

2.- 即使 ajax 调用是异步的,它们也是顺序的。也就是说,如果您发送请求,则在收到该请求的响应之前,您无法发送另一个请求。更改页面是另一个请求/响应周期,因此在收到第一个请求的响应之前,您将无法更改页面。

希望这可以帮助...

于 2012-05-17T09:58:30.870 回答
2

我找到了这篇文章,真的很失望。我的意思是在 21 世纪,异步后台请求如何阻止整个浏览器进行导航?这只是没有意义,现在应该有人解决了这个问题。

事实证明,至少在我的情况下,它不是浏览器。浏览器确实对并发请求的数量有限制,通常在六个附近。但这可以防止恶意网页的 DoS 攻击。真正的问题是 PHP。

如果 PHP 使用默认的基于文件的会话系统,那么会话将被锁定,直到它被页面退出或调用 session_write_close() 关闭;

正在发生的事情是基本页面打开会话,做它的事情然后关闭,一切都很好而且干净。现在浏览器想要在页面的一部分中进行 AJAX 处理,并回调到提供基本页面的同一服务器,该服务器重新打开会话并保持打开状态,直到 AJAXing 完成。同时,页面的另一部分也希望从具有相同会话的同一服务器动态加载某些内容。PHP 说:“不,你必须等待。会话已经被那个人打开了。” 一旦第一个 AJAX 关闭会话,第二个 AJAX 就会通过并完成它的工作。现在假设第一个电话需要 15 分钟。第二次调用和使用同一会话对同一服务器的任何链接点击都将被阻止,直到完成之前的所有加载和点击以及其他内容。恶梦!它使您的页面看起来像被冻结并且您的 AJAX 调用正在按顺序执行。嗯,他们是,但不是因为浏览器或因为 XmlHttpRequest。

我们如何解决这个问题?最简单的方法是打了就跑。如果您的页面不需要在前几行代码之后读取或写入会话,那么一旦您获取数据,请调用 session_write_close()。这将解锁会话,其他人可以使用它。我正在猜测下一部分,但我认为它会起作用。如果您稍后需要写入会话,而不是将其保持打开状态,请将其关闭以便其他人可以使用它,然后保存您的会话 ID 并稍后使用 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.

于 2018-08-18T00:02:52.960 回答