我有一个论坛(使用 PHP 和 Symfony2 框架),我想要一些非常接近实时通知的东西。我更具体地想要的是,当用户收到私有(private)消息时,会出现通知。我尝试过使用长轮询技术,但遇到了问题。
因此,我从 javascrip 向 php 发送 ajax 调用。 PHP 接收它并向数据库进行查询,以查看 ajax 请求的用户是否有任何新通知。如果它找到某些东西,它会返回该结果,否则休眠 x 秒。这是在 while(true) 条件下发生的。问题是,如果它找不到东西,它就会休眠,然后再次搜索,然后再次休眠,依此类推,当这种情况发生时,其他任何事情都不起作用。如果我尝试重新加载页面、单击论坛中的某些内容、阅读主题等等,所有这些都会被阻止,等待 ajax 调用完成。我该怎么做才能使该 ajax 调用与其他所有内容并行运行,或者在 ajax 未完成时解锁服务器。
这是我在 javascript 中的内容:
function poll() {
$.ajax({
type: "post",
url: url to the action from controller,
async: true,
data: { 'userId': $('#userId').attr('data-value') },
dataType: "json",
success: function(result) {
call method to display the notification(s) to the user
setTimeout(poll, 5000);
}
});
};
$(document).ready(function(){
poll();
});
这是 Symfony2 Controller 的操作:
public function checkForNewNotificationsAction($userId) {
while (true) {
/** @var \Forum\CoreBundle\Entity\Notification[] $notifications */
$notifications = query the database
if ($notifications != null) {
return new JsonResponse($notifications);
} else {
sleep(5);
}
}
}
我还尝试使用“纯”PHP 代码调用常规 PHP 文件,认为 Controller 的操作以及 Symfony2 管理 Controller 的方式会阻止我的其他事件,但它的作用完全相同。
我试图不使用任何其他“工具”,例如 Node.js 和 Socket.io 或类似的东西,因为我从未使用过它们,而且真的没有时间学习。该项目必须在几天内完成,而且还有很多工作要做。另外,我试图避免每 x 秒进行一次简单的 ajax 调用,将此作为我的最后一个选择。
最佳答案
这是很自然的,因为脚本正在获取 session 锁定。
添加 session_write_close();
到 Ajax 操作的开头,以便释放锁。您基本上所做的就是告诉 php,您不会再写入 session ,因此释放锁,这样可以处理并发请求。注意不要在进行此调用后写入 session 。
官方来源:session_write_close()
更新:
symfony 的 SessionInterface
有一个 save
方法,该方法又调用 session_write_close()
,您应该使用它而不是 session_write_close
.例如:
$request->getSession()->save();
当你想再次写入 session 时,你应该调用SessionInterface::start
。
关于javascript - Ajax 调用会阻塞服务器直到完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32029656/