jjzjj

javascript - SSE 加载大量数据并使 AJAX post 请求瘫痪

coder 2024-04-20 原文

这是我的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 post 请求。

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

可能是我对它们的理解不够透彻。如果可以将其归结为更简单的术语,请这样做!

提前致谢!

最佳答案

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

使用 while 循环时遇到问题的原因是 while 循环内没有 sleep() 或等待操作。因此,您正在以最大速率向客户端发送数据(一遍又一遍地发送相同的数据!)。

从概念上讲,我猜您想要的是这段代码:

$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 秒 sleep 以找到服务器 CPU 使用率和延迟之间的平衡。更短的 sleep 意味着更低的延迟(您的客户端更快地获取新数据),但服务器上的 CPU 更高。

旁白:上面的lastID 方法只是检测您已经看到和还没有看到哪些记录的某种方法。如果您的表中有一个唯一的 ID 就好了,它是 AUTO_INCREMENT。但是,或者,如果使用 created 时间戳插入数据库记录,则查询变为:

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

(稍微安全一点的是将 $now 设置为在结果中找到的最大 created 时间戳,而不是为每个 time()时间;否则记录可能会漏掉而无法发送给客户。)

关于javascript - SSE 加载大量数据并使 AJAX post 请求瘫痪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30174557/

有关javascript - SSE 加载大量数据并使 AJAX post 请求瘫痪的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  3. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  4. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  5. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  6. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  7. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  8. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  9. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  10. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

随机推荐