Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript PHP/JS进度条_Javascript_Php_Jquery_Ajax_Server Sent Events - Fatal编程技术网

Javascript PHP/JS进度条

Javascript PHP/JS进度条,javascript,php,jquery,ajax,server-sent-events,Javascript,Php,Jquery,Ajax,Server Sent Events,我正在尝试创建一个页面,它将从复杂的数据库查询和php解析生成一个结果集。。。但这主要是离题了。。。主要的一点是,这需要一两分钟来完成,我希望显示一个进度条,而不是一个通用的gif动画“加载…”图片 崩溃将是 用户打开页面A 页面A从页面B请求数据(很可能是AJAX) 页面B处理数据库中的100000多个条目并解析它们 页面A显示了一个进度条,大致显示了流程完成的程度 第B页返回结果集 页面A显示结果集 我知道如何将数据返回到ajax查询,但我的问题是我不知道如何连续返回数据以显示流程的状态

我正在尝试创建一个页面,它将从复杂的数据库查询和php解析生成一个结果集。。。但这主要是离题了。。。主要的一点是,这需要一两分钟来完成,我希望显示一个进度条,而不是一个通用的gif动画“加载…”图片

崩溃将是

  • 用户打开页面A
  • 页面A从页面B请求数据(很可能是AJAX)
  • 页面B处理数据库中的100000多个条目并解析它们
  • 页面A显示了一个进度条,大致显示了流程完成的程度
  • 第B页返回结果集
  • 页面A显示结果集
我知道如何将数据返回到ajax查询,但我的问题是我不知道如何连续返回数据以显示流程的状态(例如扫描的行的百分比)

我已经研究了EventSource/Server发送的事件,这显示了希望,我只是不太确定如何让它正常工作,或者是否有更好的方法来做

我尝试过使用EventSource创建一个快速的小模型页面,效果很好,但是当我将其拆分为一个EventSource调用(监控会话变量变化的页面)和一个ajax请求(实际的数据发送/返回)时,它就崩溃了

我可能错过了一些明显的东西,或者做了一些愚蠢的错误,但这就是我所拥有的大部分。。。任何帮助、建议、小贴士,甚至完全其他方式的建议都将非常棒:)

用户页面:

<!DOCTYPE html>
<html>
<head>
    <title>Dynamic Progress Bar Example</title>
    <script src="script.js"></script>
</head>
<body>
    <input type="button" value="Submit" onclick="connect()" />
    <progress id='progressor' value="0" max='100' style=""></progress>
</body>
</html>

在类似的情况下,我通常这样做:

  • 客户端向页面B发送AJAX请求。 重要信息:成功后,客户端再次发送相同的请求
  • 在最初的请求中,B页显示:
    好的,有54555条记录。
    。我使用此计数启动进度条
  • 在接下来的每个请求中,页面B都返回一块数据。客户端计算块的大小并更新进度条。它还收集一个列表中的块
  • 在最后一个请求中,当发送所有数据时,B页显示:
    就这些了
    ,客户端呈现数据
我想,你已经明白了


注意:您可以并行请求所有块,但这是一种复杂的方法。服务器(第B页)也应该在初始响应中返回一个固定的chunksize,然后客户端同时发送
TOTAL_COUNT/CHUNK_SIZE
请求,并合并响应,直到最后一个请求完成。所以速度要快得多。在这种情况下,您可以使用它使代码更具可读性。

那里有许多类似的问题和答案↑ →我看的那些人都没有回答我的问题(或者至少他们似乎没有回答)。例如,许多是关于文件上传的,这依赖于文件上传的特定变量和函数。我想,除了如何做之外,我在这里还想问的是:是否有可能让服务器将进度推给用户,而不是让用户不断地请求进度。(如SSE)啊,好吧-对于“推送”通知(la COMET),您可能会发现这很有用:这是一个过于简化的解决方案:a页调用B页启动作业,B页将其进度写入带有作业编号的辅助表。页面A每x秒轮询一次进度数据库,获取数据,如第1步(共1000步)。然后,您可以使用简单的数学计算%并适当地输出进度条。另一种解决方案是使用websocket。我只在socket.io和node.js中使用过WebSocket,但似乎有针对WebSocket的php解决方案:WebSocket非常好,因为一旦建立了连接,它们允许客户端或服务器启动数据传输。哦,好吧,那么初始请求告诉用户期望值,而其他每一个请求都包含数据,因此用户的浏览器可以查看收到的数量与期望的数量??就是这个主意吗?是的,就是这个主意。额外好处:一次性分配大量内存不会杀死用户的浏览器。你甚至可以在“幕后”渲染每个区块,这样你就不会因为一次性渲染大量DOM节点而扼杀用户的浏览器。我想你需要考虑在数据丢失或错误或其他情况下该怎么做。。。我想发送“这是第三包”可以解决一些问题。。。不管怎么说,我会调查这个问题,其实我没有考虑过……)我想主要的问题是如何让服务器在第一个请求时启动进程,然后在下面的请求中返回部分数据。。。有什么建议吗?因为通常每次查询时,至少在我看到的脚本中,它都会重新启动(新实例),而不是从早期实例中获取数据……没有什么能阻止您在第一条消息中发送一些独占标志,如
GIMME data
。在服务器上,您可以使用一些会话在php进程之间共享状态(我的意思是,在不同的请求之间)。但我建议您创建幂等服务器处理程序并在客户机上管理分块,比如:客户机:
您有多少记录?查询:“ABC”
服务器:
我有55565台
,客户端:
给我0-99台。查询:“ABC”
,服务器:
OK
,客户端:
给我100-199。查询:“ABC”
,服务器:
OK
,等等。。。因此,除了数据获取和错误抛出之外,服务器上不需要任何逻辑。客户端管理块和错误处理。
 var es;

   function connect() {
       startListener();
       $.ajax({
           url: "server.php",
           success: function() {
               alert("Success");
           },
           error: function() {
               alert("Error");
           }
       });
   }

   function startListener() {
       es = new EventSource('monitor.php');

       //a message is received
       es.addEventListener('message', function(e) {
           var result = JSON.parse(e.data);

           if (e.lastEventId == 'CLOSE') {
               alert("Finished!");
               es.close();
           } else {
               var pBar = document.getElementById('progressor');
               pBar.value = result;
           }
       });

       es.addEventListener('error', function(e) {
           alert('Error occurred');
           es.close();
       });
   }

   function stopListener() {
       es.close();
       alert('Interrupted');
   }

   function addLog(message) {
       var r = document.getElementById('results');
       r.innerHTML += message + '<br>';
       r.scrollTop = r.scrollHeight;
   }
<?php
SESSION_START();
header('Content-Type: text/event-stream');
// recommended to prevent caching of event data.
header('Cache-Control: no-cache'); 

function send_message($id, $data) {
    $d = $data;
    if (!is_array($d)){
        $d = array($d);
    }

    echo "id: $id" . PHP_EOL;
    echo "data: " . json_encode($d) . PHP_EOL;
    echo PHP_EOL;

    ob_flush();
    flush();
}


$run = true;
$time = time();
$last = -10;

while($run){
    // Timeout kill checks
    if (time()-$time > 360){
        file_put_contents("test.txt", "DEBUG: Timeout Kill", FILE_APPEND);
        $run = false;
    }

    // Only update if it's changed
    if ($last != $_SESSION['progress']['percent']){
        file_put_contents("test.txt", "DEBUG: Changed", FILE_APPEND);
        $p = $_SESSION['progress']['percent'];
        send_message(1, $p); 
        $last = $p;
    }

    sleep(2);
}
?>
<?PHP
    SESSION_START();

    file_put_contents("log.log", "Job Started\n", FILE_APPEND);

    $job = isset($_POST['job']) ? $_POST['job'] : 'err_unknown';
    $_SESSION['progress']['job'] = $job;
    $_SESSION['progress']['percent'] = 0;

    $max = 10;
    for ($i=0; $i<=$max;$i++){
        $_SESSION['progress']['percent'] = floor(($i/$max)*100);
        file_put_contents("log.log", "Progress now at " . floor(($i/$max)*100) . "\n", FILE_APPEND);
        sleep(2);
    }

    file_put_contents("log.log", "Job Finished", FILE_APPEND);
    echo json_encode("Success. We are done.");
?>
<?php
    SESSION_START();
    file_put_contents("log.log", "PR: Request Made", FILE_APPEND);

    if (isset($_SESSION['progress'])){
        echo json_encode(array("job"=>$_SESSION['progress']['job'],"progress"=>$_SESSION['progress']['percent']));
    } else {
        echo json_encode(array("job"=>"","progress"=>"error"));
    }
?>
<!DOCTYPE html>
<html>
<head>
        <title>Progress Bar Test</title>
</head>
<body>
        <input type="button" value="Start Process" onclick="start('test', 'pg');"/><br />
        <progress id="pg" max="100" value="0"/>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <script type="text/javascript">
            var progress = 0;
            var job = "";

            function start(jobName, barName){
                startProgress(jobName, barName);
                getData(jobName);
            }

            function getData(jobName){
                console.log("Process Started");
                $.ajax({
                    url: "server.php",
                    data: {job: jobName},
                    method: "POST",
                    cache: false,
                    dataType: "JSON",
                    timeout: 300,
                    success: function(data){
                        console.log("SUCCESS: " + data)
                        alert(data);
                    },
                    error: function(xhr,status,err){
                        console.log("ERROR: " + err);
                        alert("ERROR");
                    }
                });
            }

            function startProgress(jobName, barName){
                console.log("PG Process Started");
                progressLoop(jobName, barName);
            }

            function progressLoop(jobName, barName){
                console.log("Progress Called");
                $.ajax({
                    url: "progress.php",
                    cache: false,
                    dataType: "JSON",
                    success: function(data){
                        console.log("pSUCCESS: " . data);
                        document.getElementById(barName).value = data.progress;
                        if (data.progress < 100 && !isNaN(data.progress)){
                            setTimeout(progressLoop(jobName, barName), (1000*2));
                        }
                    },
                    error: function(xhr,status,err){
                        console.log("pERROR: " + err);
                        alert("PROGRESS ERROR");
                    }
                });
            }
        </script>
</body>
</html>
PR: Request Made
Job Started
Progress now at 0
Progress now at 10
Progress now at 20
Progress now at 30
Progress now at 40
Progress now at 50
Progress now at 60
Progress now at 70
Progress now at 80
Progress now at 90
Progress now at 100
Job Finished
PR: Request Made