在脚本完成之前返回从php到ajax的响应

时间:2016-08-18 14:38:27

标签: php jquery ajax

我有一个简单的AJAX请求到PHP文件。一旦PHP脚本到达某一点,我希望响应完成并发送回客户端。之后我仍然需要PHP脚本来运行一个最多需要15秒的函数。目前,浏览器在处理响应之前等待整个PHP脚本完成。我曾尝试使用flush();ob_flush();,但在发送响应之前,它仍然等待PHP脚本完成运行。

JQuery代码:

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代码:

if ($script_reached_this_point) {

    // ob_start();
    echo json_encode(['success' => 'Ticket added']);
    //flush();
    //  ob_end_flush();

    run_15_second_function();

}

1 个答案:

答案 0 :(得分:2)

我通过使用2个PHP脚本解决了类似的问题。我们称他们为receiver.phpworker.php。过程如下:

  1. AJAX调用receiver.php
  2. receiver.php在辅助连接中调用worker.php,向其传递作业说明并等待第一行响应。
  3. 一旦第一行回复从worker.php到达,receiver.php就会关闭该连接
  4. receiver.php立即返回对AJAX的响应并退出。
  5. worker.php继续在后台工作
  6. <强> 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();