微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

javascript – SSE加载大量数据并使AJAX发布请求陷于瘫痪状态

这是我的sse_server.PHP文件

include_once 'server_files/init2.PHP'; //this file includes the connection file to the database and some functions

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

$assocArray = array();

$fetch_article = $dbh->prepare("SELECT 
                                        article_author_id,article_author_un,article_id,article_cover,article_title,article_desc
                                    FROM articles ORDER BY article_id DESC");
$fetch_article->execute();

while ($fetch = $fetch_article->fetch(PDO::FETCH_ASSOC)) 
{
    $article_author_id    = $fetch['article_author_id'];
    $article_author_u     = $fetch['article_author_un'];
    $article_id           = $fetch['article_id']; 
    $article_cover        = $fetch['article_cover'];
    $article_title        = $fetch['article_title'];
    $article_desc         = $fetch['article_desc'];


    $randomNum = rand(0,500);

    //Insert the Random Number along with the article's info | Random Number as a Value and the contents as a Key
                $assocArray[
                            'randomNum'.'|'.                    //0
                            $article_author_id.'|'.             //1
                            $article_author_u.'|'.              //2
                            $article_id.'|'.                    //3
                            $article_cover.'|'.                 //4
                            $article_title.'|'.                 //5
                            $article_desc                       //6

                            ]  = $randomNum;
}

//sort the array
arsort($assocArray,1); 
//echo '<pre>';
//print_r($assocArray);

//while(true){

    $var = '';
    foreach ($assocArray as $key => $value) {

        $var .=  $value .' => ' . $key . '`|||`<br>';
    }
    echo "retry: 6000\n";
    echo "data: {$var}\n\n";
    ob_flush();
    flush();

//}

这就是我在client.PHP文件中处理数据的方式

<div id="Feeds"></div>
    <script>

        if(typeof(EventSource)!=="undefined") {

            var eSource = new EventSource("sse_server.PHP");


            //detect message received
            eSource.addEventListener('message',function(event) {


            var jsV_Feeds = event.data;
            var eventList = document.getElementById("Feeds");


            var jsV_FeedsArray = jsV_Feeds.split('`|||`');  //Seperator



            eventList.innerHTML = jsF_ToFetch(jsV_FeedsArray); 

            },false);
        }
        else {
            document.getElementById("Feeds").innerHTML="Whoops! Your browser doesn't receive server-sent events.";
        }


        function jsF_ToFetch(jsP_array) 
        {
            var string = ''; //an empty string 
            for (var i = 0; i < jsP_array.length-1; i++) 
            {

                jsV_Feed = jsP_array[i].split('|');

                jsV_randomNum           = jsV_Feed[0];
                jsV_article_author_id   = jsV_Feed[1];
                jsV_article_author_u    = jsV_Feed[2];
                jsV_article_id          = jsV_Feed[3];
                jsV_article_cover       = jsV_Feed[4];
                jsV_article_title       = jsV_Feed[5];
                jsV_article_desc        = jsV_Feed[6];


                string += jsV_randomNum +'<li><b>'+jsV_article_author_u+'</b><!--process the rest in a similar way--> </li>';


            } // for loop ENDS here
            return '<ol>' + string + '</ol>';
        }

    </script>

问题是如果我只使用foreach循环,它每6秒重新连接一次.
如果我将foreach包装在while循环中,它会使连接保持活动状态,但不断继续发送数据.这最终会在几秒钟内加载大量数据.此外,它使AJAX Post请求非常慢,同时通过另一个页面执行.

为什么会这样?
如何让它保持连接打开,不发送数据,而不是减慢AJAX发布请求的速度.

PS:我访问过这些链接
http://www.html5rocks.com/en/tutorials/eventsource/basics/
PHP Event Source keeps executing

可能是我对他们的理解不够.如果它可以归结为更简单的术语,请善待它!

提前致谢!

解决方法

您希望使用在sse_server.PHP中注释掉的while(true){}循环.您的SSE脚本永远不会退出(直到套接关闭,这将发生在客户端,即您的JavaScript脚本关闭它,或者浏览器窗口关闭).

使用while循环时遇到问题的原因是while循环内没有sleep()或wait动作.因此,您将以最大速率向客户端发送数据(一遍又一遍地重复相同的数据!).

从概念上讲,我猜你所追求的是这段代码

$lastID = 0;
while(true){
  $fetch_article = $dbh->prepare("SELECT something FROM somewhere WHERE conditions AND articleID > ?");
  $results = $fetch_article->execute($lastID);
  if(has 1+ results) {
     foreach($results){
        echo result formatted for SSE
        $lastID = ...;
     }
     flush();ob_flush();
  }
  sleep(5);
}

这表示它将每隔5秒轮询数据库获取新记录.如果没有新的记录它什么都不做 – 只需再回到睡眠状态5秒钟.但如果有新的记录,它会通过SSE将它们推送给客户端.

您可以调整5秒睡眠以找到服务器上cpu使用率与延迟之间的平衡.较短的睡眠意味着较低的延迟(您的客户端可以更快地获得新数据),但服务器上的cpu更高.

旁白:上面的lastID方法只是检测你所看到的记录的一些方法,还没有看到.如果您的表中有唯一的ID,那就好了,这就是AUTO_INCREMENT.但是,或者,如果使用创建的时间戳插入DB记录,则查询将变为:

$Now = 0;
while(true){
    $stmt = prepare( "SELECT ... AND created > ?" );
    $stmt->execute( $Now );
    $Now = time();
    ...process results ...
    sleep(5);
}

(稍微更安全的是将$Now设置为在结果中找到的最大创建时间戳,而不是每次都设置为time();否则记录可能会滑过裂缝而不会被发送到客户端.)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐