I'm writing a php script that has a long execution time, and I want to be able to tell the client the scripts progress.
I can't do it with output buffering because the script is called via AJAX (and I'd like to keep it that way).
I stumbled upon a solution where you save the progress to a $_SESSION variable and make continuous calls to another PHP script to get the progress from the $_SESSION.
However, in my implementation, these calls do not execute until the main (long) process is done. In the Chrome dev tools window, the calls are showing as "Pending" along with the main AJAX call, and they all return the progress instantly after the main call finishes.

This is the main long script (test code):
<?php
@session_start();
for($i=0; $i<10; $i++)
{
$_SESSION["progress"] = $i;
sleep(2);
}
This is the updating script
<?php
if(isset($_SESSION["progress"]))
echo $_SESSION["progress"];
else
echo 0;
This is the javascript
$("form#form-main").submit(function(e) {
e.preventDefault();
var $form = $(this);
var timeout_id;
$form.find("div#popup-overlay").show();
$.ajax(
{
url: $form.attr("action"),
type: $form.attr("method"),
data: new FormData($form[0]),
cache: false,
contentType: false,
processData: false,
xhr: function()
{
//get the native XmlHttpRequest object
var xhr = $.ajaxSettings.xhr();
//update progress
xhr.upload.onprogress = function(e)
{
if(e.lengthComputable)
{
var progress = Math.ceil(e.loaded / e.total * 100);
if(progress < 100)
$form.find("div#popup-content #status").text("UPLOADING " + progress + "%");
else
{
//start getting process progress from server
timeout_id = setInterval(
function()
{
$.post(
"CheckProgress.php",
function(data)
{
$form.find("div#popup-content #status").text("PROCESSED " + data + " pages");
}
);
},
300
);
}
}
};
//return the customized object
return xhr;
},
success: function(data)
{
$form.find("div#popup-content").html(data);
}
}
);
});
What can I do to make the javascript client retrieve the progress?
onprogressonly gets called when the 1st ajax completes, since it's not an ajax call that can return a progress. Try starting your first ajax and then your 2nd ajax at the same time, one after the other.