How to Continue Process After Responding to Ajax Request in PHP

PHP with AJAX - Continue Processing After Sending Response to the User

It looks like (as @ADyson said in the comment) flushing output doesn't seem work with AJAX. So, the only solution to the problem is to use Cron Job. To do this, I used PHP Cron Scheduler. But crontab can be used directly to add a Cron Job to the list.

I added the post processes to another PHP file with suitable changes so that it can do the same tasks from the script and added the file to the Scheduler.

This solution may seem a real pain, but there is no solution to this problem other than using Cron Job.

Continue AJAX request after page refresh

The ajax request will stop. Whether or not your server processes the request will depend on whether or not the server completely received the request before it was stopped.

This is a case where it is ok to use async: false to get the behaviour you want. However, it would be better to just wait to do the refresh until the ajax is complete.

How to continue AJAX/JQuery even after the page is unloaded or redirected into another page?

You can't continue to access the results of an ajax call after the window in which it was started has been redirected to another URL. That whole context has been cleaned up by the browser and is no longer available.

You would need to stop doing the redirection until you are done with the ajax call. Some possibilities:

  1. Change from redirection to loading content via ajax so you can keep the original document open during the whole process so the ajax call will continue and you can access its results, but you're also showing the new content.

  2. Don't do the redirect until after the ajax call completes (in its completion handler).

  3. Open a new window for the redirect and when the ajax call completes, close that window. If these windows are in the same domain, you can access data between them. Personally, I'd avoid the extra window if possible.

handling long requests ajax to php

fsockopen is the best answer I could come up on this one. Hope this helps somebody down the road. The following code allows me to call file1.php via ajax which will send data to file2.php. Once file1.php sends data to file2.php using fsockopen it does not wait for a response. Additional code can be run in file1.php while file2.php is doing it's thing. File1.php can echo a response to the ajax request right away even while file2.php is still running.

This answer is only useful for someone who needs to run a long executing script that requires data in but no data back in return.

file1.php called via ajax request:

$vars = array('hello' => 'world');
$post_data = http_build_query($vars);

/// ssl and 443 are used for https, change to tls and 80 for http
/// only the main website domain is needed
/// do not put the full path to the file you need to call here
$fp = fsockopen("ssl://www.main-website-domain.com", 443, $errno, $errstr, 1);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
//// this is where the full path to the file you want to reach goes
//// format is (method) (path not including the domain) (HTTP version)
$out = "POST /Full/Path/to-test-file2.php HTTP/1.1\r\n";
$out .= "Host: www.main-website-domain.com\r\n";
$out .= "Content-Type: application/x-www-form-urlencoded\r\n";
$out .= "Content-length: " . strlen($post_data) . "\r\n";
$out .= "User-Agent: What-ever-you-want\r\n";
$out .= "Connection: close\r\n\r\n";
$out .= $post_data . "\r\n\r\n";
fwrite($fp, $out);
fclose($fp);
}

file2.php

$data = $_POST['hello'];
ignore_user_abort(true);
sleep(60);///example of a long running script
// since no data will be returned it's best to store any results in a database
// echo, print_r, var_dump, or any other display mechanism will not work in this file unless directly accessed

Continue PHP execution after sending HTTP response

Have the script that handles the initial request create an entry in a processing queue, and then immediately return. Then, create a separate process (via cron maybe) that regularly runs whatever jobs are pending in the queue.

return response to from php to ajax before script finishes

I solved a similar problem by having 2 PHP scripts. Let's call them receiver.php and worker.php. The process is as follows:

  1. AJAX calls receiver.php
  2. receiver.php calls worker.php in a secondary connection, passes it the job instructions and waits for the first line of response.
  3. As soon as the first line of response arrives from worker.php, receiver.php closes that connection
  4. receiver.php returns the response to AJAX immediately and exits.
  5. worker.php continues work in the background

receiver.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();

Storing response from php in ajax request

I'm trying to store data from ajax (jquery) response to variable because I need to use it later in code.

The accepted Answer has 'var controlNumber = $data;' declaration inside Ajax Success Callback, which wouldn't accessible from Outside of Ajax Function. That statement is very clear that You Can't get'controlNumber' variable outside of
Ajax Callback Success Function, because it's a local variable, declared inside a function.. So the best would be declare a Global JavaScript Variable and reassign value again inside Ajax Success callback.

By they way if I follow the line "I'm trying to store data from ajax (jquery) response to variable" then the accepted answer is fine.

But if I follow the statement "I need to use it later in code" creates 2 assumptions here..

1 - if your code is still on inside ajax function - Then Fine

2 - if your code using ajax response on outside ajax function, then you won't be able to get 'controlNumber' value. if you try you will get 'undefined'

So what is the best way to deal Ajax Response, Create a function which responsible to return ajax object with success or error response. I am sure it didn't sound clear.. ;) No worry here is more or read more :)

First of all understand what is ajax and how it works...?

AJAX = Asynchronous JavaScript and XML.

AJAX is a technique for creating fast and dynamic web pages.

AJAX allows web pages to be updated asynchronously by exchanging
small amounts of data with the server behind the scenes. This means
that it is possible to update parts of a web page, without reloading
the whole page.

Content Reference: W3CSCHOOL

Kindly notice the word 'asynchronously', it means if you call ajax and trying to use ajax response data at next line then you can't. Because, DOM will not wait for Ajax Response & script won't stop to wait to complete process of ajax it will continue & you will get 'undefined' until you don't make ajax request with 'async: false' option. *But as of jQuery 1.8, the use of async: false is deprecated! Wohooo!! Sounds Great!!! @-@ *

Many people also suggest to use global var and set variable value later inside ajax success callback to use. But the problem is
asap you try to use variable after next ajax call then it will produce same error as describe above.

So the best method would be to Store or Use or Get Ajax Response by
using a function which returns ajax object and you can later use that
ajax object with 'YourAjaxObject.success(callback)' anywhere
any time in your application without any worry. You can also use/put
your functions which requires ajax response inside ajax success
callback.

A very simple example I am sharing with you to understand this better..


// global var declare here
var collect = null;
$(document).ready(function() {
var btn = $('#mySubmitButton');
btn.on('click', function(e) {
e.preventDefault();
$.post('url.php', {
id: 1
}, function(ajx_res) {
// store ajax response in global var
collect = ajx_res;
// 'I will execute last with collect = ajx_res data
alert(collect);
});
// 'I will execute first with collect = null data
alert(collect);
// When btn click again, I will execute first with previous ajx_res data
alert(collect);
});
});
$(document).ready(function() {
var btn = $('#mySubmitButton');
btn.on('click', function(e) {
e.preventDefault();
$.post('url.php', {
id: 1
}, function(ajx_res) {
// now I am local var
var collect = null;
// store ajax response in local var
collect = ajx_res;
// 'I will execute last with collect = ajx_res data
alert(collect);
});
// I will execute first with collect = undefined
alert(collect);
// When btn click again I will execute first with same collect = undefined
alert(collect);
});
});
/**
* Ajax Request & Return Response
* @param url _url action url
* @param object options send payloads
*/
function AjaxCall(_url, _options) {
return $.ajax(_url, {
method: 'POST',
data: _options,
error: function(xhr, ajaxOptions, thrownError) {
alert("Request Error:" + thrownError + " with Status" + xhr.status);
}
});
}
// I am again as global var
var collect = null;
$(document).ready(function() {
var btn = $('#mySubmitButton');
// first button, click
btn.on('click', function(e) {
e.preventDefault();
// return ajax object, and can be use within entire application via callback
collect = AjaxCall(_url, _options);
// use success callback to retrieve data
collect.success(function(ajx_res) {
// I will execute first with ajx_res
alert(ajx_res);
});
});
var btns = $('#mySubmitButtons');
// on another button, another click
btns.on('click', function(e) {
e.preventDefault();
// using previous ajax obj to get data
collect.success(function(ajx_res) {
// I will execute first with previous ajx_res
alert(ajx_res);
});
});
});

// I am again as global var
var collect = null;
$(document).ready(function() {
var btn = $('#mySubmitButton');
// first button, click
btn.on('click', function(e) {
e.preventDefault();
// return ajax object, and can be use within entire application via callback
collect = AjaxCall(_url, _options);
});
var btns = $('#mySubmitButtons');
// on another button, another click
btns.on('click', function(e) {
e.preventDefault();
// using previous ajax obj to get data
collect.success(function(ajx_res) {
// I will execute first with previous ajx_res
alert(ajx_res);
});
});
});

So in short:

1 - You can't use local variable (which declared inside function or
loop) out side of their declaration area.

2 - Ajax don't return the response, you can get the response by using
callbacks.

3 - Store Ajax response in global variable to use outside of ajax
callback function.

4 - If any code, function depends on ajax response, put them inside
ajax success callback.

5 - If any specific functions needs ajax response value, then call
those functions inside success callback & pass ajax response as
parameters or you can use 'Injection Techniques' (function to function
with same parameter) e.g.

function Hello (ajx_res) {
alert (ajx_res);
// send in another function
Foo (ajx_res);
}

function Foo (ajx_res) {
alert (ajx_res);
// send in another function
Bar (ajx_res);
}

function Bar (ajx_res) {
alert (ajx_res);
}

So my answer would be for this Question use Ajax Object & Get response by Callbacks.

/**
* Ajax Request & Return Response
* @param url _url action url
* @param object options send payloads
*/
function AjaxCall(_url, _options) {
return $.ajax(_url, {
method: 'POST',
data: _options,
error: function(xhr, ajaxOptions, thrownError) {
alert("Request Error:" + thrownError + " with Status" + xhr.status);
}
});
}
$(document).ready(function() {
$("#submitReg").click(function() {
var email = $("#email").val();
var password = $("#password").val();
var confpassword = $("#confpassword").val();
if (!email || !password || !confpassword) {
swal({
type: "error",
timer: 10000,
showConfirmButton: true,
confirmButtonText: "OK",
confirmButtonColor: "#f4511e",
title: "Prosím vyplňte všetky polia!"
});
} else {
var ajaxObj = AjaxCall("./php/register.php", {
email: email,
password: password,
confpassword: confpassword,
});
// your ajax callback function for success
ajaxObj.success(function(response) {
var controlNumber = response;
if (controlNumber == '1') {
swal({
type: "success",
timer: 10000,
showConfirmButton: true,
confirmButtonText: "OK",
confirmButtonColor: "#f4511e",
title: "Registrácia prebehla úspešne."
});
} else if (controlNumber == '0') {
swal({
type: "error",
timer: 10000,
showConfirmButton: true,
confirmButtonText: "OK",
confirmButtonColor: "#f4511e",
title: "Mail už bol zaregistrovaný."
});
} else {
alert(controlNumber);
}
});
}
});
});

Hope this will clear doubts for beginners user who are not comfortable with ajax at first sight, first love :D ^_^ Tadaaa.. :)

Allow further ajax requests to php whilst processing on first request continues

Another option is to have the server return a token for any job that is in process, then have the client make a second request later to check the status of the job using a timeout. Your client code can then continue to start new requests or do other work when not actively polling for a job's status.

Here's a very simplistic example:

CLIENT:

$.ajax({
url: "startJob",
success: function(response) {
setTimeout(function(){ pollForJobStatus(response.jobToken) },3000);
}
});

function pollForJobStatus(jobToken) {
$.ajax({
url: "jobStatus",
success: function(response) {
if(response.job.status == 'done') {
// DO SOMETHING WITH THE RESULTS
}
else {
//keep polling
setTimeout(function(){ pollForJobStatus(response.jobToken) },3000);
}
}

});
}

SERVER:

*//  POST: '/startJob'*
function($data)
{
// take incoming data from client,

//start 'job' on a new thread
$job = new PdfJob($data);
$job->start();

//record the threadID info in database
DB.store($job->processId, $job->jobToken);

//return token to client
return new ApiResponse($job->jobToken);
}

*// GET: '/jobStatus'*
function($token)
{
// lookup job's process id in the db
$pId = DB.retrieve($token);

// use the processId to check the job status
$jobStatus = checkJobStatus($pId);

//return status to client
return new ApiResponse($jobStatus);
}


Related Topics



Leave a reply



Submit