Ajax调用会阻塞服务器,直到它完成

时间:2015-08-15 21:41:50

标签: javascript php jquery ajax symfony

我有一个论坛(在PHP中使用Symfony2框架),我想要一些非常接近实时通知的东西。我更想要的是,当用户收到私人消息时,会出现通知。我试过使用长轮询技术,但我遇到了问题。

所以,我从javascrip发送ajax调用到php。 PHP接收它并向数据库发出查询,以查看是否有针对ajax请求的用户的任何新通知。如果它找到了什么,它会返回该结果,否则会休息x秒。这发生在一段时间(真实)的情况下。问题是,如果它没有找到某些东西,它会睡觉,然后再次搜索,然后再次睡觉等等,而这种情况发生时没有其他工作。如果我尝试重新加载页面,点击论坛中的某些内容,阅读主题等等,所有内容都会被阻止等待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控制器的动作:

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文件,认为来自控制器的操作以及Symfony2如何管理控制器阻止了我的其他活动,但它完全相同。

我正在尝试不使用任何其他“工具”,如Node.js和Socket.io或类似的东西,因为我从未与他们合作,实际上没有时间学习。该项目必须在几天内完成,仍有很多工作要做。此外,我试图每隔x秒避免简单的ajax调用,将此作为我的最后选择。

1 个答案:

答案 0 :(得分:-1)

“解决”这个“qucik and dirty way”:

您可以执行以下操作,而不是在PHP代码中实际向数据库发出请求:

  • 创建一个名为dbchanged.txt的文件,内容为“0”
  • 当您更改数据库中的某些内容时,您将更改该文件的内容“1”。
  • 当您从ajax执行请求时,请检查dbchanged.txt的内容
    • 如果dbchanged.txt的内容为“1”,则执行db-request。完成此请求后,将dbchanged.txt内容更改为“0”,然后返回。
    • 如果dbchanged.txt的内容为“0”,则只返回而不执行任何db-request。

为什么我说“解决”这是因为它实际上并没有解决问题,但它会更快,因为它(通常)quciker读取文件而不是访问数据库。另一方面,您可能不得不面对文件锁定问题 - 取决于我们正在讨论的请求数量。

以正确的方式行事!

没有“快捷方式”解决您的问题,我真的建议您阅读长期请求和websockets。使用 sockets.IO 似乎并不困难,并且是一种比上面更好的解决方案 - 以下是如何创建聊天应用程序(以及如何理解代码中的内容) :http://socket.io/get-started/chat/

HTML5 websockets并非在所有浏览器中都可用,但socketIO(使用html5 websockets)会为您完成这项工作,并且当websockets不可用时使用长拉技术。

jquery和socketIO示例: https://gist.github.com/anandgeorge/2814934

另一个可能有用的参考资料: http://techoctave.com/c7/posts/60-simple-long-polling-example-with-javascript-and-jquery