处理对PHP的长请求ajax

时间:2018-07-10 13:10:42

标签: php jquery ajax multithreading curl

我有一个正在处理的Web应用程序,用户单击该按钮可以向php文件发起ajax请求。 php文件需要很长时间才能运行,这迫使用户在通知用户请求已完成之前要等到php文件运行完毕。

以下是我使用的代码示例:

jQuery调用者:

$('#button').click(function(){
 $.ajax({
    type: "POST",
    url: 'index-process.php',
    success: function (data) {
            console.log(data);
            alert('finished');
    }
 });
});

index-process.php

<?php

/// placeholder for a long script
sleep(60);
echo "finished processing";

?>

我正在寻找某种解决方法,可以让我通知用户该请求已提交。然后,让代码在后台完成运行。我不一定需要我的PHP脚本将任何值返回给用户。它只需要执行。

到目前为止,我已经使用带有2个不同php文件的curl请求尝试了类似的操作,但是它仍然迫使用户等待两个php文件运行完毕,然后再完成ajax请求:

index-process.php

<?php

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, 'index-process2.php');
curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'do_nothing');
curl_exec($ch);  
curl_close($ch);
echo "finished processing";

function do_nothing($curl, $input) {
    return 0; // aborts transfer with an error
}
?>

index-process2.php

<?php
ob_end_clean();
ignore_user_abort(true);
ob_start();
header("Connection: close");
header("Content-Length: " . ob_get_length());
ob_end_flush();
flush();

/// placeholder for a long script
sleep(60);
?>

如果没有使用php的好的解决方案,是否有可能使用jQuery的解决方案?如果是这样,有人可以告诉我正确的编码方式吗?

2 个答案:

答案 0 :(得分:0)

fsockopen是我能想到的最佳答案。希望这可以帮助别人。以下代码允许我通过ajax调用file1.php,它将把数据发送到file2.php。一旦使用fsockopen将file1.php发送数据到file2.php,它就不会等待响应。可以在file2.php执行此操作时在file1.php中运行其他代码。即使file2.php仍在运行,File1.php仍可以立即响应对ajax请求的响应。

此答案仅对需要运行长时间执行脚本且需要输入数据但没有返回数据的人有用。

通过ajax请求调用的

file1.php:

$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   

答案 1 :(得分:0)

对于使用php-fpm(即nginxapache通过mod_fcgi的人),您可以使用fastcgi_finish_request来实现所描述的行为。

它做什么

fastcgi_finish_request会将输出发送到客户端(浏览器),但是它将执行该函数之后指定的所有代码。

示例

echo "Request accepted";

fastcgi_finish_request(); // Sends "Request accepted" back to web server, but executed all code below

// Do your long running task
sleep(60);