多个AJAX请求相互延迟

我的页面上有一个很长的轮询请求。 服务器端的脚本在20秒后设置为超时。

因此,当长轮询“空闲”并且用户按下另一个按钮时,该新请求的发送被延迟,直到前一个脚本超时。

我看不出jQuery方面的代码有什么问题。 为什么onclick事件会延迟?

function poll() { $.ajax({ url: "/xhr/poll/1", data: { user_id: app.user.id }, type: "POST", dataType: "JSON", success: pollComplete, error: function(response) { console.log(response); } }); } function pollComplete() { poll(); } function joinRoom(user_id) { $.ajax({ url: "/xhr/room/join", dataType: "JSON", type: "POST", data: { user_id: app.user.id, room_id: room.id } }); }  ############ PHP Controller on /xhr/poll $time = time(); while ((time() - $time) getNewStuff(); foreach ($updates->getResult() as $update) $response[] = $update->getResponse(); if (!empty($response)) return $response; else usleep(1 * 1000000); return 'no-updates'; } 

“usleep”可能成为问题吗?

XHR截图

如果在AJAX处理函数中使用会话,则会遇到第一个请求锁定磁盘会话数据的问题,因此每个后续请求都会在会话数据继续之前等待会话数据可用。 实际上,这会使异步调用相互阻塞,最终会按时间顺序对请求进行线性响应 – 同步。 ( 这是一篇参考文章 )

解决方案是使用session_write_close ( docs )在您不再需要会话时立即关闭会话。 这允许其他后续请求继续进行,因为会话数据将被“解锁”。

然而,这也会让人感到困惑。 如果你在返回响应之前调用session_write_close ,那么你不会给自己任何好处,因为一旦发送响应,会话就会被解锁。 因此,需要尽早调用它。 如果您正在使用回发式架构来处理AJAX请求,这不是很糟糕,但如果您有一个更大的框架而您的请求处理程序只是其中的一部分,那么您将不得不探索更高级的解决方案非阻塞会话使用,因此您的子组件没有关闭框架期望仍然打开的会话。

一种方法是使用数据库会话。 这个解决方案的优点和缺点超出了这个答案的范围 – 请查看Google进行详尽的讨论。 另一种方法是使用一个打开会话,添加变量然后关闭它的函数。 您可以通过此解决方案冒险竞争条件,但这是一个粗略的概述:

 function get_session_var($key, $default=null) { if (strlen($key) < 1) return null; if (!isset($_SESSION) || !is_array($_SESSION)) { session_start(); session_write_close(); } if (array_key_exists($key, $_SESSION)) return $_SESSION[$key]; return $default; } function set_session_var($key, $value=null) { if (strlen($key) < 1) return false; if ($value === null && array_key_exists($key, $_SESSION)) { session_start(); unset($_SESSION[$key]); } elseif ($value != null) { session_start(); $_SESSION[$key] = $value; } else { return false; } session_write_close(); return true; } 

这听起来与2请求规则一致 – 浏览器在任何给定时间只允许两个并发连接到同一主机。 话虽如此,你应该没有长时间的轮询(接收)和发送频道。 你是否在使用$(function(){…?页面加载后开始长轮询?你确定请求在客户端上被延迟了,而不是在浏览器中吗?你在firebug中看到了什么?

您可以做的一件事是,您可以中止正在运行的民意调查并首先运行您的请求,然后再次启动民意调查。

 //make sure pollJqXhr.abort is not undefined var pollJqXhr={abort:$.noop}; function poll() { //assign actual jqXhr object pollJqXhr=jQuery.ajax({youroptions}); } function pollComplete() { poll(); } function joinRoom(user_id) { //pause polling pollJqXhr.abort(); jquery.ajax({ /*options here*/ success:function() { /*Your codes*/ //restart poll poll() } }); }