问题
I've Looked at ajax progress bar solutions on this site,
However i can't find anything to help with the below,
basically,[browser] ----> makes ajax call to [server running php]
my php code
<?php
//input and process ajax request
//[MySQL] processing 5000 rows of a table
//after 5000/5000 row, end of ajax call
?>
Now, I need to show the user the status of the rows being processed
eg Processing::::::::: 2322/5000. row
The code for processing Mysql looks like this
foreach($result_set as $table_row)
{
// process each table row
}
How am i going to let the client know of this progress via xmlhttprequest? cannot use JQUERY, only Javascript
Tried implementing the below,
the server continously echos the progress in a loop,
<?php
//progress
while($i < $total_progress)
{
//php processing
if(@ob_get_contents()){ ob_end_flush(); flush(); }
echo $i; // progress
$i++;
}
?>
The Data (variable $i) is continously being printed and pushed into the response,
Is there a way i can read the printed variable from the server,constantly before the ajax call ends?
回答1:
This can be done with a combination of AJAX, sessions, and javascript. I've never made any graphical versions of a bar, but I have made text-based ones in the past.
In your client side page, have AJAX make a call to your page that will do the table processing. Have this server side page start a session and create a session variable to track what your progress is at (e.g. $_SESSION['processedRows']
). Now inside your processing loop after you processed a row, increase the value of your session var and then make a call to session_write_close()
. This will write your session info to disk and then close the session. This is important, as I will explain in a minute. You must also make another call to session_start()
again prior to updating your session variable in the next iteration of your foreach
loop.
Back on the client side, you will have another AJAX request being sent on an interval (I use setInterval()
in javascript for this) which will call up another server side page that will open a session and return the value of $_SESSION['processedRows']
. You can take this value and use it update your counter, progress bar, etc. You could return several values as JSON or an HTML snippet, doesn't matter. Just make sure that you have a callback method of some kind in place that will kill the interval that has been setup on the client side. It is important that you call session_write_close()
in your long running script. If you do not then your concurrent script to check the progress will not be able to access your session variables and will lag while it waits for the processing script to end. The reason is that the session file has not been released until you call session_write_close()
.
EDIT:
Here is a very basic, no frills example of what you are looking for. This doesn't have much in regards to error checking, timeouts, etc. But it should illustrate what you want done. No jQuery either, as per you question. For this you will need three files. First you need your long running script, this one basically puts PHP to sleep very briefly 5000 times. It is to illustrate your table operations.
startCounter.php
<?php
//Start a long-running process
$goal = 5000;
session_start();
for($i = 0; $i < $goal; $i++) {
session_start(); //Reopen session to continue updating the progress
if(!isset($_SESSION['progress'])) {
$_SESSION['progress'] = $i;
$_SESSION['goal'] = $goal;
}
//wait a wink
usleep(rand(500, 2000));
$_SESSION['progress'] = $i;
session_write_close(); //Close session to gain access to progress from update script
header_remove();
}
?>
Next you need an update script, this one is very simple, it will only output a string with the progress update.
updateCounter.php
<?php
//Get the progress
session_start();
print("Processed " . $_SESSION['progress'] . " of " . $_SESSION['goal'] . " rows.");
?>
Next you need your client side ready to go with AJAX. You need to have a way to start the long running script, and then while that request is incomplete, you set and interval to hit the server up for the current progress. Just make sure you kill the interval when operation is done. Here is the test page:
progress.html
<!DOCTYPE html>
<html>
<head>
<title>Progress Test</title>
<script language="javascript">
function go()
{
var xhr = new XMLHttpRequest();
xhr.open("GET", "startCounter.php", true);
interval = window.setInterval( function () {
update();
}, 200);
xhr.onreadystatechange = function () {
if(xhr.readyState == 4) {
window.clearInterval(interval);
//Extremely likely that the AJAX update function won't make it in time to catch
//the script at 5000 before it wins. So let's display a message instead showing
//that everything is done.
document.getElementById("updateme").innerHTML = "Operation has completed.";
}
}
xhr.send();
}
function update()
{
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if(xhr.readyState == 4 && xhr.status == 200) {
document.getElementById("updateme").innerHTML = xhr.responseText;
}
}
xhr.open("GET", "updateCounter.php", true);
xhr.send();
}
</script>
</head>
<body>
<form>
<input type="button" onclick="go()" value="Go!" />
</form>
<h3>AJAX update test</h3>
<h4 id="updateme"></h4>
</body>
</html>
Hope that gets you going in the right direction.
来源:https://stackoverflow.com/questions/22686298/streaming-progress-in-ajax-from-php-server-processing-database