php - PHP 和 Ajax 的进度条

标签 php jquery post request progress

我正在研究使用 ajax 请求和 session 变量更新进度的进度条。当我的程序执行耗时的操作(例如发送许多电子邮件等)时,它只是设置适当的 session 变量(其中包含进度值)。此操作由以下代码中的函数 post() 启动。

与此同时,第二个函数 ask() 每 500 毫秒循环执行一次。它应该实时返回当前进度。这就是问题所在:ask() 发送的每个请求都在等待 post() 函数发送的请求完成。有趣的是,如果我设置一些 URL,比如 google.com 而不是 url/to/progress,它就可以正常工作,只是它不是我想要的 :)。这意味着问题出在服务器端。

不确定它是否重要,但我使用 Yii 框架。

下面的所有代码都只是草稿(但有效),其唯一目的是展示我的意思。

提前致谢。

抱歉我的英语不好:)

查看部分:

<script type="text/javascript">
function ask() {
  var d = new Date();
  var time = d.getTime();
  $.ajax({

    type: 'get',
    url: '/url/to/progress' + '?time=' + time,
    success: function(data) {
      $("#progress").html(data);
    }
  })
}

function post() {
  var d = new Date();
  var time = d.getTime();

  $.ajax({
      type: 'post',
      url: '/url/to/post' + '?time=' + time,
      data: {"some": "data"},
      success: function(data) {alert(data)}
    });
}

$("#test").click(
  function() {
    post();
    var progress = setInterval("ask();", 500);
  }
);
</script>

Controller 部分:

public function actionPost($time) {
  sleep(5); // time consuming operation
  echo $time . ' : ' . microtime();
  exit;
}

public function actionProgress($time) {
  echo $time . ' : ' . microtime();
  exit;
}

最佳答案

我认为您的问题与 session 相关。

当脚本有一个打开的 session 时,它会锁定 session 文件。这意味着任何使用相同 session ID 的后续请求都将排队,直到第一个脚本释放它对 session 文件的锁定。您可以使用 session_write_close() 强制执行此操作- 但这并不能真正帮助你,因为你正试图与 session 文件共享进度信息所以 post脚本需要保持 session 数据打开和可写。

您需要想出另一种在 post 之间共享数据的方式。和 progress脚本 - 如果 post在整个执行过程中打开 session 数据,progresspost 之前将永远无法访问 session 数据执行完毕。也许您可以使用 session ID 创建一个临时文件 post具有写入权限,您可以在其中放置进度指示器数据。 progress可以检查文件并返回该数据。 IPC(进程间通信)有很多选项 - 这不是一个特别漂亮的选项,但它确实具有最大可移植性的优势。

作为旁注 - 请不要将字符串传递给 setInterval() , 传递函数。所以你的行实际上应该是:

var progress = setInterval(ask, 500);

但是 - 使用 setTimeout() 会更好在success/error ask() 的处理程序 Ajax 功能。这是因为通过使用 setInterval() , 无论前一个请求的状态如何,都会发起一个新的请求。等到上一个请求完成后再发起下一个请求会更有效率。所以我会做更像这样的事情:

<script type="text/javascript">

  // We'll set this to true when the initail POST request is complete, so we
  // can easily know when to stop polling the server for progress updates
  var postComplete = false;

  var ask = function() {

    var time = new Date().getTime();

    $.ajax({

      type: 'get',
      url: '/url/to/progress' + '?time=' + time,

      success: function(data) {
        $("#progress").html(data);
        if (!postComplete)
          setTimeout(ask, 500);
        }
      },
      error: function() {
        // We need an error handler as well, to ensure another attempt gets scheduled
        if (!postComplete)
          setTimeout(ask, 500);
        }
      }

    });

  }

  $("#test").click(function() {

    // Since you only ever call post() once, you don't need a seperate function.
    // You can just put all the post() code here.

    var time = new Date().getTime();

    $.ajax({

      type: 'post',
      url: '/url/to/post' + '?time=' + time,
      data: {
        "some": "data"
      },

      success: function(data) {
        postComplete = true;
        alert(data);
      }
      error: function() {
        postComplete = true;
      }

    });

    if (!postComplete)
      setTimeout(ask, 500);
    }

  });

</script>

...尽管这仍然不能解决 session 问题。

关于php - PHP 和 Ajax 的进度条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9311986/

相关文章:

PHPSpreadsheet:如何获取加载的行数?

javascript - 如何多次调用一个函数?

JQuery 将文本框集合设置为空值

java - JSoup 登录网站

php - 代码点火器 + Angular Js : How to receive JSON data

php - 添加类以在 Symfony FormBuilder 中选择选项

php - 将 JavaScript 变量分配给 Smarty 变量

php - 如何将这个多计数循环编写为单个查询?

javascript - 保存ajax调用的id以在返回函数中使用它

api - api POST Auth始终返回200,但出现401错误