【问题标题】:ajax php foreach loop update after each iteration每次迭代后ajax php foreach循环更新
【发布时间】:2016-04-09 17:01:02
【问题描述】:

我想要做的是使用 jQuery/Ajax 向 PHP 脚本发出请求,并在每次 foreach 循环完成时返回状态更新。我想用输出做一个进度条。

我遇到的问题是 jQuery 只会在整个脚本完成后更新页面。有没有办法强制 jQuery 或 PHP 在每个循环上输出,而不仅仅是将其全部转储到 success 函数上。

        jQuery(document).ready(function($) {            
            $(document).on('click','#fetch-snowfall-data a',function () {
              $(this).text('Fetching Snowfall Data...');
                $.ajax({
                    type: "GET",
                    async: true,
                    url: "url.php",  
                    data:{},                
                    dataType: "html", 
                    success: function(response){
                        $("#response_container").append(response);
                        $('#fetch-snowfall-data a').text('Fetch Snowfall Data');
                    }
                }); 
            return false;
            });
        });

PHP

foreach ( $results['resorts'] as $resort ) {

    //Do all the things here

    $count++;
    echo $count .'/'. $results['total_rows'];

}

【问题讨论】:

  • 不是真的,您可能需要 SSE、Sockets 或为此进行轮询,您通常无法返回部分内容(但可以通过刷新)
  • 一个简单的解决方案是添加beforeSend: 属性并放置一个函数,该函数将用旋转gif 或其他东西填充您的容器,这样至少人们会看到它正在做某事。您需要一个更复杂的 jquery:*.com/questions/19139613/… 才能获得实际进展。
  • @Rasclatt 我之前尝试过,但无法从中获得任何输出。它没有详细说明任何服务器端代码,所以我不确定如何构建输出
  • @adeneo 我尝试使用冲洗无济于事。我一直在研究 SSE,但还没有找到相关的示例或教程。如果您知道任何请分享
  • 所以示例中列出的console.log(percentComplete) 在您的控制台中没有产生任何内容?

标签: php jquery ajax foreach


【解决方案1】:

根据 adeneo 的建议,我认为您不能返回部分内容。我之前试图对此进行研究,但无济于事。但是,如果有人能纠正我,我将非常感激。

对我来说最终结果是做递归 ajax。

javascript

var data = '';
$(document).on('click','#fetch-snowfall-data a',function () {
  ajaxCall(0);
});

function ajaxCall(num) {
  $.ajax({
    type: "POST",
    async: true,
    url: "url.php",
    data: num,
    dataType: "json",
    xhr:function(){
        //progress bar information here.
    },
    success: function(response) {
      $("#response_container").append(response['data']);
      if (response['check'] === 'next') {
        var nextNum = num +1;
        data += response['data'];
        ajaxCall(nextNum); //call itself for the next iteration
      }else if (response['check'] === 'done'){
        data = response['data'];
        //do stuff with the data here.
      }else if (response['check'] === 'error') {
        return response['data'];
      }
    },
    error:function(xhr, status,error){
        //error information here
    }
  });
}

对于 PHP:

只要确保你在 json 中输出包含两个信息的东西。 Json.check:看是否要进入下一次迭代,完成并输出数据,还是报错。 Json.data 输出它需要的任何数据。您需要做的是在没有foreach 循环的情况下一次输出每个报告

--编辑--

我发现了一些关于 php 流式传输的主题

  1. http://www.sitepoint.com/php-streaming-output-buffering-explained/
  2. Best approach for (cross-platform) real-time data streaming in PHP?

【讨论】:

  • coldfusion 是可能的,但我不是 php 开发人员,所以不知道是否可以用 php 完成。查看数据流和/或刷新缓冲区。
  • @KevinB 谢谢,我一定会调查的。好像跑nodejs会比php好?
  • 两者都可以实现相同的效果,所以这取决于个人喜好。我更喜欢 node.js
【解决方案2】:

感谢大家的帮助。我最终设法让这一切正常工作,并将确切地分享我是如何做到的,以便其他人未来受益。

需要 3 个文件 - 您从中加载的页面、处理脚本和侦听脚本。

您需要知道要处理多少行才能使一切正常工作。我从loading.php中的php变量$results['total_rows'];加载我的

正在加载.php

       jQuery(document).ready(function($) {
            setTimeout(getProgress,1000);
            $(document).on('click','#fetch-snowfall-data a',function () {
              $(this).text('Fetching Snowfall Data...');
                $.ajax({
                    url: 'process.php',
                    success: function(data) {
                        $("#response_container2").append(data);
                    }
                });
                setTimeout(getProgress,3000);
            return false;
            });
            function getProgress(){
                $.ajax({
                    url: 'listen.php',
                    success: function(data) {
                        if(data<=<?php echo $results['total_rows']; ?> && data>=1){
                            console.log(data);
                            $('#response_container').html('<div id="progress"><div class="progress-bar" role="progressbar" style="width:'+ (data / <?php echo $results["total_rows"] ?>)*100 +'%">'+ data + '/' +<?php echo $results["total_rows"] ?> +'</div></div>');
                            setTimeout(getProgress,1000);
                            console.log('Repeat');
                        } else {
                            $('#fetch-snowfall-data a').text('Fetch Snowfall Data');
                            console.log('End');
                        }
                    }
                });
            }
        });

进程.php

foreach ( $results['resorts'] as $resort ) { 

    //Do all the things here you want to.

    $count++;
    session_start();
    $_SESSION['progress'] = $count;
    $_SESSION['total'] = $results['total_rows'];
    session_write_close();
    sleep(1);
}

unset($_SESSION['progress']);

听.php

session_start();
echo (!empty($_SESSION['progress']) ? $_SESSION['progress'] : '');

if (!empty($_SESSION['progress']) && $_SESSION['progress'] >= $_SESSION['total']) {
    unset($_SESSION['progress']);
}

进度条的一些 CSS

#progress {
    height: 20px;
    margin-bottom: 20px;
    /* overflow: hidden; */
    background-color: #f5f5f5;
    border-radius: 4px;
    -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
    box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
}
.progress-bar {
    float: left;
    width: 0;
    height: 100%;
    font-size: 12px;
    line-height: 20px;
    color: #fff;
    text-align: center;
    background-color: #337ab7;
    -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);
    box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);
    -webkit-transition: width .6s ease;
    -o-transition: width .6s ease;
    transition: width .6s ease;
}

【讨论】: