使用 PHP 和 AJAX 进行长轮询...几乎完成

发布于 2024-11-09 06:52:46 字数 4527 浏览 0 评论 0原文

我正在处理一个学校项目。该项目的基本思想是,我们有一些 arduino 盒子,它们将一些传感器数据发送到 mysql 数据库,并且我们有一个显示它的网站。假设每 6 秒发送一次传感器数据。

我对 PHP 没有太多经验。但我正在修补我的方式,一步一步学习..牛仔风格? =)

html/ajax/css:

    <!DOCTYPE html>
<html>
<head>
    <title>Arduino event poller</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript" charset="utf-8"></script>

    <style type = "text/css" media="screen">
        body{ font:13px/1.5 "helvetica neue", helvetica, arial, san-serif; background:#FFF; }
        #main{ width:430px; height: 300px; display:block; padding:10px 0; float: left; overflow: auto;}
        .event { display:block; background: #ececec; width:380px; padding:10px; margin:10px; overflow:hidden; text-align: left; }  
        .event img { display:block; float:left; margin-right:10px; }  
        .event p { font-weight: bold; }
        .event img + p { display:inline; }
        .patient-name { display:inline; color: #999999; font-size: 9px; line-height:inherit; padding-left: 5px; }
        .event-text{ color: #999999; font-size: 12px; padding-left: 5px; }
        .event-timestamp{ color: #000; padding-left: 5px; font-size: 9px;}
    </style>

    <script type="text/javascript" charset="utf-8">

        var timeStamp = null;

        /* Simple helper to add some divs.*/
        function addevents(patientroom, patientname, eventtyp, timestamp)
        {
            $("#main").append(
                "<div class='event'>"
                "<p>" + patientroom + "</p>"
                "<p class='patient-name'>" + patientname + "</p>"
                "<p class='event-text'>" + eventtyp + "</p>"
                "<p class='event-timestamp'>" + timestamp + "</p>"
                "</div>"
                );
        }

        /*This requests the url "getevents.php" When it complete*/
        function waitForEvents()
        {
            $.ajax({
                type: "GET",
                url: "getevents.php?timeStamp=" + timeStamp,

                async: true, /* If set to non-async, browser shows page as "Loading.."*/
                cache: false,
                timeout:50000, /* Timeout in ms */

                success: function(data, textStatus, jqXHR) /* called when request to getevents.php completes */
                {
                    addevents(data.patientroom, data.patientname, data.eventtyp, data.timestamp);
                        setTimeout(
                          waitForEvents, /* Request next event */
                          1000 /* ..after 1 seconds */                   
                        );
                    },
                error: function (XMLHttpRequest, textStatus, errorThrown){
                    alert("Error:" + textStatus + " (" + errorThrown + ")");
                    setTimeout(
                        'waitForEvents()', /* Try again after.. */
                        "5000"); /* milliseconds (5seconds) */      
                },
            });
        };

        $(document).ready(function(){
                waitForEvents(); /* Start the inital request */
        });
    </script>
</head>
<body>
    <div id="main">
    </div>
</body>
</html>

我的后端 php:

<?php
function getEvents()
{
    $con = mysql_connect("localhost","***","***");
        if(!con)
        {
            die('Could not connect: ' . mysql_error());
        }
        mysql_select_db("arduino_db",$con);

    $result = mysql_query("SELECT * FROM events ORDER BY eventID DESC LIMIT 1");
    if($result)
    {
        $patientroom = $row['rumNr'];
        $patientname = $row['inneboendeNamn'];
        $eventtyp = $row['handelse'];
        $timestamp = $row['timestamp'];
    }

    if($row)
    {
        header('application/json');
                echo json_encode($row);
                exit;
    }

    $lastmodif = isset($_GET['timeStamp']) ? $_GET['timeStamp'] : 0;
    $currentmodif = filemtime($result);

    while($currentmodif <= $lastmodif)
    {
        unsleepp(1000);
        clearstatcache();
        $currentmodif = filemtime($result);
    }
}

?>

我的问题:

  1. 如何从数据库中获取每一行并返回每一行以 JSON 格式发送到前端的“waitForEvents”方法。

该示例不必是可扩展的、安全的或完整的,它只需要工作=)

更新:基于约翰提示的新代码。我得到的只是一个空白页,没有错误。

I am working with a school project. The basic ide of the project is, that we have some arduino boxes the sends some sensor data to a mysql db and we have a website that display it. Sensor data is sending lets say every 6sec.

I don´t have a lot of experience with PHP. But i am tinkerin my way, learing step by step..cowboy style? =)

The html/ajax/css:

    <!DOCTYPE html>
<html>
<head>
    <title>Arduino event poller</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript" charset="utf-8"></script>

    <style type = "text/css" media="screen">
        body{ font:13px/1.5 "helvetica neue", helvetica, arial, san-serif; background:#FFF; }
        #main{ width:430px; height: 300px; display:block; padding:10px 0; float: left; overflow: auto;}
        .event { display:block; background: #ececec; width:380px; padding:10px; margin:10px; overflow:hidden; text-align: left; }  
        .event img { display:block; float:left; margin-right:10px; }  
        .event p { font-weight: bold; }
        .event img + p { display:inline; }
        .patient-name { display:inline; color: #999999; font-size: 9px; line-height:inherit; padding-left: 5px; }
        .event-text{ color: #999999; font-size: 12px; padding-left: 5px; }
        .event-timestamp{ color: #000; padding-left: 5px; font-size: 9px;}
    </style>

    <script type="text/javascript" charset="utf-8">

        var timeStamp = null;

        /* Simple helper to add some divs.*/
        function addevents(patientroom, patientname, eventtyp, timestamp)
        {
            $("#main").append(
                "<div class='event'>"
                "<p>" + patientroom + "</p>"
                "<p class='patient-name'>" + patientname + "</p>"
                "<p class='event-text'>" + eventtyp + "</p>"
                "<p class='event-timestamp'>" + timestamp + "</p>"
                "</div>"
                );
        }

        /*This requests the url "getevents.php" When it complete*/
        function waitForEvents()
        {
            $.ajax({
                type: "GET",
                url: "getevents.php?timeStamp=" + timeStamp,

                async: true, /* If set to non-async, browser shows page as "Loading.."*/
                cache: false,
                timeout:50000, /* Timeout in ms */

                success: function(data, textStatus, jqXHR) /* called when request to getevents.php completes */
                {
                    addevents(data.patientroom, data.patientname, data.eventtyp, data.timestamp);
                        setTimeout(
                          waitForEvents, /* Request next event */
                          1000 /* ..after 1 seconds */                   
                        );
                    },
                error: function (XMLHttpRequest, textStatus, errorThrown){
                    alert("Error:" + textStatus + " (" + errorThrown + ")");
                    setTimeout(
                        'waitForEvents()', /* Try again after.. */
                        "5000"); /* milliseconds (5seconds) */      
                },
            });
        };

        $(document).ready(function(){
                waitForEvents(); /* Start the inital request */
        });
    </script>
</head>
<body>
    <div id="main">
    </div>
</body>
</html>

My backend php:

<?php
function getEvents()
{
    $con = mysql_connect("localhost","***","***");
        if(!con)
        {
            die('Could not connect: ' . mysql_error());
        }
        mysql_select_db("arduino_db",$con);

    $result = mysql_query("SELECT * FROM events ORDER BY eventID DESC LIMIT 1");
    if($result)
    {
        $patientroom = $row['rumNr'];
        $patientname = $row['inneboendeNamn'];
        $eventtyp = $row['handelse'];
        $timestamp = $row['timestamp'];
    }

    if($row)
    {
        header('application/json');
                echo json_encode($row);
                exit;
    }

    $lastmodif = isset($_GET['timeStamp']) ? $_GET['timeStamp'] : 0;
    $currentmodif = filemtime($result);

    while($currentmodif <= $lastmodif)
    {
        unsleepp(1000);
        clearstatcache();
        $currentmodif = filemtime($result);
    }
}

?>

My question:

  1. How to I fetch each row from the db and return each row in JSON format to the method "waitForEvents" in the frontend.

The example doesn't have to be scaleable, secure or complete, it just needs to work =)

UPDATE: new code based on Johns tips. All I gets is a blank page, and no errors.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽袖吟 2024-11-16 06:52:46

我首先想到的是你的 MySQL 调用有点失败。

当您运行此行时:

$result = mysql_query("SELECT * FROM events ORDER BY eventID DESC LIMIT 1");

您将获得 MySQL 资源。您需要利用它来获取行:

$result = mysql_query("SELECT * FROM events ORDER BY eventID DESC LIMIT 1");
if ($result)
{
   $row =  mysql_fetch_assoc($result);
   if ($row)
   {
        // Your result is here, as a big associative array.  Each column in your 
        // table is now keyed to this array.  Exact fields will depend on your DB.
        //
        // Just access it like something like this:

        $id = $row['id'];
        $time = $row['time_stamp'];

   }
}

将其作为 JSON 回显:

... // snip
   if ($row)
   {
        header('application/json');
        echo json_encode($row);
        exit;
   }
}
// handle your errors!

添加:在 OP 问题中发现其他错误:

//  The following line isn't valid.  This isn't what you'll get back from $.ajax.
//    success: function(patientroom, patientname, eventtyp, timestamp) 

//  Corrected code:
success: function(data, textStatus, jqXHR) 
/* called when request to getevents.php completes */
{
    addevents(data.patientroom, data.patientname, data.eventtyp, data.timestamp);
    setTimeout(
      waitForEvents, /* Request next event */
      1000 /* ..after 1 seconds */                   
    );
},

进一步更新。你混合了&与上面的代码匹配。

$result = mysql_query("SELECT * FROM events ORDER BY eventID DESC LIMIT 1");
if($result)
{
   // this has to go inside of this check.  This is where you *ASSIGN* $row.
   $row =  mysql_fetch_assoc($result);

   // You need to rekey $row before you output:
   $retVal = array('patientroom'=>$row['rumNr'],
                   'patientname'=>$row['inneboendeNamn'],
                   'eventtyp'=>$row['handelse'],
                   'timestamp'=>$row['timestamp']);

   // I'm not sure what you're doing with the incoming timestamp.  Should we just
   // return it back out?
   $retVal['ajax_timestamp'] = $_GET['timeStamp'];

   header('application/json');
   echo json_encode($retVal);
   exit; // this exits. Comment this out if you want, but don't try to write anything else out to the buffer.
}

// Not sure what you're trying to do here.  I'll comment out for now.
/*
$lastmodif = isset($_GET['timeStamp']) ? $_GET['timeStamp'] : 0;
$currentmodif = filemtime($result);

while($currentmodif <= $lastmodif)
{
    unsleepp(1000);
    clearstatcache();
    $currentmodif = filemtime($result);
}
*/

}

The first thing that popped out to me is that your MySQL call is sort of blown.

When you run this line:

$result = mysql_query("SELECT * FROM events ORDER BY eventID DESC LIMIT 1");

You're going to get a MySQL resource. You need to utilize that to get your row:

$result = mysql_query("SELECT * FROM events ORDER BY eventID DESC LIMIT 1");
if ($result)
{
   $row =  mysql_fetch_assoc($result);
   if ($row)
   {
        // Your result is here, as a big associative array.  Each column in your 
        // table is now keyed to this array.  Exact fields will depend on your DB.
        //
        // Just access it like something like this:

        $id = $row['id'];
        $time = $row['time_stamp'];

   }
}

to echo it back out as JSON:

... // snip
   if ($row)
   {
        header('application/json');
        echo json_encode($row);
        exit;
   }
}
// handle your errors!

added: Additional error found in OP question:

//  The following line isn't valid.  This isn't what you'll get back from $.ajax.
//    success: function(patientroom, patientname, eventtyp, timestamp) 

//  Corrected code:
success: function(data, textStatus, jqXHR) 
/* called when request to getevents.php completes */
{
    addevents(data.patientroom, data.patientname, data.eventtyp, data.timestamp);
    setTimeout(
      waitForEvents, /* Request next event */
      1000 /* ..after 1 seconds */                   
    );
},

Further updates. You mixed & matched the code from above.

$result = mysql_query("SELECT * FROM events ORDER BY eventID DESC LIMIT 1");
if($result)
{
   // this has to go inside of this check.  This is where you *ASSIGN* $row.
   $row =  mysql_fetch_assoc($result);

   // You need to rekey $row before you output:
   $retVal = array('patientroom'=>$row['rumNr'],
                   'patientname'=>$row['inneboendeNamn'],
                   'eventtyp'=>$row['handelse'],
                   'timestamp'=>$row['timestamp']);

   // I'm not sure what you're doing with the incoming timestamp.  Should we just
   // return it back out?
   $retVal['ajax_timestamp'] = $_GET['timeStamp'];

   header('application/json');
   echo json_encode($retVal);
   exit; // this exits. Comment this out if you want, but don't try to write anything else out to the buffer.
}

// Not sure what you're trying to do here.  I'll comment out for now.
/*
$lastmodif = isset($_GET['timeStamp']) ? $_GET['timeStamp'] : 0;
$currentmodif = filemtime($result);

while($currentmodif <= $lastmodif)
{
    unsleepp(1000);
    clearstatcache();
    $currentmodif = filemtime($result);
}
*/

}

冬天旳寂寞 2024-11-16 06:52:46

我知道你不应该用 php 进行长轮询。如果您不是专业的 php 黑客,那么这会很混乱,并且由于许多其他原因,例如:

  • PHP 是为了快速执行(而不是等待)
  • PHP 将迫使您在服务器端进行某种轮询并依赖 sleep()
  • PHP会吃掉你的RAM,同时每个请求的生成进程也会吃掉(Apache会这样做)

我的项目需要的是显示新数据而不刷新漏洞站点。我是这样做的:

<script type="text/javascript">
        var timeoutId;
        var intervalId;

        function doIt(){
            $("#main").load("refresh.php");
        }
        $(document).ready(function(){
            timeoutId = setTimeout(function(){
                doIt();
                intervalId = setInterval(function(){
                    doIt();
                }, 5000); //Request the doIt() method every 5ms.
            }, 3000); //Delay calculated on the server to trigger the function at the appropriate time
        }); 
    </script>   

I understand know that you shouldnt do long-polling with php. It's to messy if you aint a pro php-hacker and for many other reasons like:

  • PHP is made for fast execution (not for waiting)
  • PHP will force you to do some kind of polling on the server side and relying on sleep()
  • PHP will eat your RAM while so are spawning processes for each requests (Apache will do so)

The thing I need for my project is to show new data without refreshing the hole site. I did it like this:

<script type="text/javascript">
        var timeoutId;
        var intervalId;

        function doIt(){
            $("#main").load("refresh.php");
        }
        $(document).ready(function(){
            timeoutId = setTimeout(function(){
                doIt();
                intervalId = setInterval(function(){
                    doIt();
                }, 5000); //Request the doIt() method every 5ms.
            }, 3000); //Delay calculated on the server to trigger the function at the appropriate time
        }); 
    </script>   
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文