【问题标题】:Navigate to another page after sending a long XMLHttpRequest发送长 XMLHttpRequest 后导航到另一个页面
【发布时间】:2018-08-18 08:02:52
【问题描述】:

我有一个 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。似乎它们同时发生。我确实在readyState==4httpRequest.responseText; 中看到了返回的文本。

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

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

【问题讨论】:

  • 第一个行为可以很容易地被 jquery 删除。 jquery 是您可以选择的选项吗?
  • 可能,但我更喜欢理解这种行为并从基础解决它,而不是操纵解决方案......
  • 你可以在onreadystatechange函数外设置“请稍候”,当readyState变为4时将其删除。该行为可能是由于ajax逐块加载文件引起的。

标签: php javascript ajax asynchronous xmlhttprequest


【解决方案1】:

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

ReadyStates

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

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

希望这会有所帮助...

【讨论】:

  • 所以基本上当你发送一个 XMLHttpRequest 时,在请求完成之前你不能再次调用服务器,你只能做客户端操作,对吧?
  • 是的,除非您在正常窗口中执行其他操作时打开第二个浏览器窗口来为您处理事情
  • +1 在搜索为什么我在发送 ajax 调用时无法导航到另一个页面的答案时来到这里,你的第二部分答案是我的答案。不知道它仍然是顺序的,即使它是异步的
【解决方案2】:

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

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

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

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

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

更难的方法是编写自己的不锁定会话处理程序。这实际上就是我所做的。我有一个不锁定的基于 Cassandra 的会话处理程序。不利的一面是我受到“最后获胜”并发的影响,但在我的情况下,只有我的基本页面实际写入会话,我的 AJAX 调用不写入任何内容,所以这不是问题。如果您没有锤子,就无法破坏您的数据。

希望这会有所帮助,因为虽然最初的答案有助于解决我的问题,但这是对实际情况的完全误解。异步 XmlHttpRequest 不是顺序的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-16
    • 2012-09-18
    • 2021-09-20
    • 2020-07-27
    相关资源
    最近更新 更多