Reputation: 27
I have a simple AJAX request that to a PHP file. Once the PHP script reaches a certain point I would like for the response to be completed and sent back to the client. After that I still need the PHP script to run a function that takes up to 15 seconds. Currently the browser waits for the entire PHP script to finish before processing the response. I have tried to use flush();
or ob_flush();
, but it still waited for the PHP script to finish running before sending the response.
JQuery code:
jQuery.ajax({
url: "../phpFile.php",
data: formdata,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function (data) {
data = $.parseJSON(data);
if(data.success){
window.location = "../public/dashboard.php";
}
}
});
PHP code:
if ($script_reached_this_point) {
// ob_start();
echo json_encode(['success' => 'Ticket added']);
//flush();
// ob_end_flush();
run_15_second_function();
}
Upvotes: 1
Views: 3214
Reputation: 40896
I solved a similar problem by having 2 PHP scripts. Let's call them receiver.php
and worker.php
. The process is as follows:
receiver.php
receiver.php
calls worker.php
in a secondary connection, passes it the job instructions and waits for the first line of response.worker.php
, receiver.php
closes that connectionreceiver.php
returns the response to AJAX immediately and exits.worker.php
continues work in the backgroundreceiver.php
//data to be forwarded to worker.php
$postData = json_encode($_POST);
// headers for the connection to worker.php
$headers = "POST /path/to/worker.php HTTP/1.1".PHP_EOL;
$headers .= "Host: localhost".PHP_EOL;
$headers .= "Content-Length: ".strlen($postData).PHP_EOL;
$headers .= "Content-Encoding: none".PHP_EOL;
$headers .= "Content-Type: application/json".PHP_EOL;
// create socket to the local webserver for calling background script
$socketToWorker = fsockopen("localhost", 80, $errno, $err_msg);
if(!$socketToWorker) die("fsockopen error #$errno: $err_msg");
// Make the request and send the POST data
fwrite($socketToWorker, $headers.PHP_EOL.$postData);
//read until the 1st packet is returned, then stop. 8192 is arbitrary
//but needs to be greater than the expected response from worker.php
$data = fread($socketToWorker,8192);
fclose($socketToWorker);
//send response to browser (work still ongoing in background)
if($data==='OK') echo "Success";
else echo "Background work failed. Error: $data";
worker.php
//parse input from receiver.php
$postData = json_decode(file_get_contents('php://input'),true);
//TODO: validate $postData.
// If data is valid, set below to 'OK' to accept the job
$acceptJob = 'OK'; //replace with an error message to reject the job
ob_start(); //start the buffer
echo $acceptJob; //this is what receiver.php will see
//set headers for the response to receiver.php
header("Content-Encoding: none");
header('Connection: close');
header('Content-Length: '.ob_get_length() );
// flush buffer. Will cause receiver.php to receive data and disconnect
ob_end_flush(); ob_flush(); flush();
if($acceptJob!=='OK') exit;
##################### START THE JOB HERE #####################
set_time_limit(60); //only needed if you expect job to last more than 30 secs
run_15_second_function();
Upvotes: 3