为什么这个PHP挂起页面?

时间:2016-06-18 20:54:52

标签: php jquery ajax apache

在页面上,我有按钮来启动和取消要在服务器端以PHP执行的任务。当这些PHP任务正在运行时,用户无法离开页面,它只会挂起,直到作业完成。我试图找到导致同步行为的原因。

Jquery的:

$(document).ready(function() 
{
  var id = 0;

  $('#tool-execute-btn').click(function()
  {
    // Pull data from page

    var last_response_len = false;
    $.ajax( 
    {
      xhrFields: 
      {
        onprogress: function(e)
        {
          var this_response, response = e.currentTarget.response;

          if(last_response_len === false)
          {
            this_response = response;
            last_response_len = response.length;
          }
          else
          {
            this_response = response.substring(last_response_len);
            last_response_len = response.length;
          }

          // Get the data from the stream (backend php)
          $('#tool-output-area').append(this_response + '<br>');
      }
    },
    method: 'POST',
    url: 'run-tool.php', // See block below
    data:
    { 
        // Data from page
    }
  }) // ... Continue

后台处理PHP页面:

/* Setup the page so I can stream the content
 * line by line back to the user */
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

/* Set Maximum Execution Time By Plan */
ini_set('max_execution_time', getMaxExeTime());

ini_set('output_buffering', 'off');
ini_set('zlib.output_compression', false);
ini_set('implicit_flush', true);

ob_implicit_flush(true);

while (ob_get_level() > 0) 
{
  $level = ob_get_level();
  ob_end_clean();
  if (ob_get_level() == $level) break;
}

if (function_exists('apache_setenv')) 
{
  apache_setenv('no-gzip', '1');
  apache_setenv('dont-vary', '1');
}

/* This section runs a ping and echos out the terminal window */
$descriptorspec = 
[
  0 => ['pipe', 'r'],
  1 => ['pipe', 'w'],
  2 => ['pipe', 'w']
];

// Input checking for the post data and interaction with a MySQL database is done here

$tool_command = 'ping 8.8.8.8 -n 10';

$process = proc_open($tool_command, $descriptorspec, $pipes);
stream_set_blocking($pipes[1], false);
stream_set_blocking($pipes[2], false);
$proc_details = proc_get_status($process);

while ($s = fgets($pipes[1])) 
{
  echo $s;
  flush();
  sleep(0.3);
}

如果在此while循环期间的任何时间用户尝试重新加载页面,他们将只获取标签加载图标。如果我尝试从jQuery运行另一个PHP脚本,它只会排队直到while循环完成。造成这个问题的原因是什么? PHP,Ajax,apache服务器,HTTP请求,还有什么?

1 个答案:

答案 0 :(得分:1)

在脚本中使用会话变量时,一次只能有一个脚本调用访问同一个会话,而PHP会阻止来自同一客户端的任何其他脚本。

在脚本访问会话变量时使用session_write_close(),这将允许运行另一个脚本。如果需要再次访问会话变量,则需要再次调用session_start()