4

我希望在我的社交网站上实现实时通知更新。我对彗星做了一些研究,我真的很着迷。

据我了解,这是彗星服务器上发生的基本流程。

Webpage: 
Sends an ajax request to server when the document is ready. 

Server:
Queries the database every x amount of seconds and returns a json string containing results if any are found.

Webpage:
Receives the result of the json string from the server and sends out another ajax request  to do the above process again.

通过了解 Comet 的工作流程,我编写了一些 PHP 和 Javascript 代码。

JavaScript 代码使用 jQuery 库并将 ajax 请求发送到服务器,并将当前时间以 unix 时间戳格式作为 GET 参数。

    $(document).ready(function(){
       var timestamp = Math.round(new Date().getTime() / 1000);

        function comet2(){
            $.ajax({
                type : 'GET',
                url  : 'comet.activities.php?timestamp=' + timestamp,
                async : true,
                cache : false,

                success : function(data) {
                    alert("current timestamp "+timestamp)

                    var json = JSON.parse(data);
                    if(json !== null){
                        alert(data);
                    }

                    timestamp  = json[0].timestamp;
                    setTimeout('comet2()', 1000);

                },
                error : function(XMLHttpRequest, textstatus, error) { 
                    setTimeout('comet2()', 15000);
                }       
            });
        }

        //call the comet function because the page has loaded.
        comet2();

    });

PHP 代码将通过使用时间戳参数(在本例中为查询中的 unix 时间戳)在数据库中搜索新行来查询新活动。对于此示例,我将结果数量限制为 1。

<?php 
    set_time_limit(0);
    include("models/config.php");
    global $mysqli,$db_table_prefix;

    $last = isset($_GET['timestamp']) ? $_GET['timestamp'] : 0;
    $results = null;
    $flag=true;

    $stmt = $mysqli->prepare("SELECT id,timestamp FROM uc_user_activity WHERE timestamp > ? ORDER BY timestamp DESC LIMIT 0,1");
    $stmt->bind_param("i", $last);
    $stmt->bind_result($id,$timestamp);

    while($flag){
        $stmt -> execute();    

        while ($row = $stmt->fetch()){
            $flag = false;
            $results[] = array(
                "id" => $id,       
                "timestamp" => $timestamp  
            );
        }

        $stmt -> close();  

        usleep(100000);
        clearstatcache();
    }

    echo json_encode($results);    

?> 

上面的代码实际上并没有“工作”问题是,如果用户发布新评论,当彗星脚本运行时,它将无法添加到数据库中。这意味着彗星脚本将永远不会返回任何 json 结果,因为永远不会满足 sql 查询中的语句(没有使用更新的时间戳添加新活动)。我用于发布新评论的 ajax 代码 100% 正常工作,所以我知道这不是问题所在。简单地说“什么都没有发生”,即没有任何(没有错误)被警告或输出到浏览器控制台。

编辑号 3:我很难解释“什么都没有发生”的意思,所以我上传了一张图片,显示当从 jquery 调用彗星脚本时数据库插入失败(注意文本框是如何被禁用的,而评论是通过ajax发布的)。

在此处输入图像描述

我能做些什么呢?我花了几个小时在互联网上搜索试图解决这个问题/找到一个类似的工作示例但无济于事。

如果我将 PHP 代码中的查询更改为:

$stmt = $mysqli->prepare("SELECT id,timestamp FROM uc_user_activity WHERE timestamp **<** ? ORDER BY timestamp DESC LIMIT 0,1");

代替:

 $stmt = $mysqli->prepare("SELECT id,timestamp FROM uc_user_activity WHERE timestamp > ? ORDER BY timestamp DESC LIMIT 0,1");

结果会立即通知浏览器窗口,可以再次发布评论并再次调用脚本并显示新帖子。这表明我的代码毕竟“工作正常”,而且看起来查询导致了问题......

在此处输入图像描述

谁能看到这里发生了什么?我现在已经编辑了这个问题 7 次,任何指导都会很棒,因为我一无所获。

只是为了避免关闭,这是我的问题,以总结我上面讨论的内容:

有没有更好的方法来实现彗星服务器?我不是最有经验的人,但我真的很想学习如何做到这一点。似乎 StackOverflow 具有此功能并且运行良好 - 他们是如何做到的?

我不可能写出比这更详细的帖子了,我真的很感谢你们这些很棒的人提供的一些指导。关于为什么我的代码“不起作用”的建议或任何解释如何实现它的教程的链接将是惊人的!提前感谢并为这个怪物的问题和所有的编辑道歉!

4

2 回答 2

0

我的预感是您传递的时间戳值不会返回任何结果。您可以通过 Javascript 获取当前时间。查询查询此时间戳之后的所有帖子。

您可以尝试打印查询并手动运行相同的查询以确保它从数据库中检索数据吗?

于 2013-04-09T04:57:15.120 回答
0

因此,这里有关于 Comet 与 PHP 的最佳可用教程。 http://www.zeitoun.net/articles/comet_and_php/start

喜欢它,如果它有帮助:)

对于那些想要在上面与 jQuery 的链接中使用简单聊天解决方案的人来说,这里是解决方案。

<script type="text/javascript">
    var Comet = {};
    Comet.jquery = {
        timestamp: 0,
        url: './backend.php',
        noerror: true,
        initialize: function () {
        },
        connect: function ()
        {
            this.ajax = $.ajax({
                type: "get",
                url: this.url,
                data: {timestamp: this.timestamp},
                success: function (data) {
                    // handle the server response
                    var response = JSON.parse(data);
                    console.log(response);
                    //alert(response.timestamp);
                    Comet.jquery.timestamp = response.timestamp;
                    Comet.jquery.handleResponse(response);
                    Comet.jquery.noerror = true;
                },
                complete: function (data) {
                    // send a new ajax request when this request is finished
                    if (!Comet.jquery.noerror) {
                        // if a connection problem occurs, try to reconnect each 5 seconds
                        setTimeout(function () {
                            Comet.jquery.connect()
                        }, 5000);
                    }
                    else {
                        Comet.jquery.connect();
                    }
                    Comet.jquery.noerror = false;
                }
            });
        },
        disconnect: function ()
        {
        },
        handleResponse: function (response)
        {
            $('#content').append('<div>' + response.msg + '</div>');
        },
        doRequest: function (request)
        {
            $.ajax({
                type: "get",
                url: this.url,
                data: {'msg': request}
            });
        }
    }
</script>
于 2014-09-17T07:09:07.483 回答