如何在没有 PHP Pusher 的情况下制作实时进度条
How To Make Realtime Progressbar Without PHP Pusher
我陷入了这个问题,关于在 php 上制作实时进度条(没有 php 推送器)
假设我有 10 行数据,这些数据将被插入到数据库中。
现在如何发送进度条数据,同时也插入到数据库中。
非常感谢您的回答。
谢谢
下面是我的代码示例:
// script.js (client)
// This function executed when user submit form
function store() {
// Listen Server Side Event
let event = new EventSource('controller/store')
event.addEventListener('message', response => {
// Then update progressbar
updateProgressbar(response.percent)
})
// Ajax to save data to database
$.ajax({
url: baseUrl + 'controller/store',
type: 'POST',
dataType: 'JSON',
data: $('#form').serializeArray(),
success: function(response) {
console.log(response)
}
})
}
// Controller.php (server)
public function store() {
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");
header("Connection: keep-alive");
$total_row = count($_POST['customer']);
for ($i = 0; $i < $total_row; $i++) {
usleep(100000);
$this->db->insert('customers', $_POST['customer'][$i]);
$percent = ($i + 1) * (100 / $total_row);
echo "event: message\n";
echo 'data: {"status": "loading", "percent": "' . $percent . '"}';
echo "\n\n";
ob_end_flush();
flush();
if (connection_aborted()) break;
}
echo "event: message\n";
echo 'data: {"status": "done", "percent": "' . $percent . '"}';
echo "\n\n";
}
Web 服务器和浏览器不会按照您想要的方式运行。
HTTP headers 包含内容长度,Web 服务器在将文档发送到客户端之前希望知道该长度。除非您已经确切知道文档 body 的长度,否则服务器将(通常)等到 PHP 脚本退出后再向客户端发送任何信息。
ob_end_flush()
和flush()
不直接向客户端发送信息;将它发送到 Web 服务器,它仍然会缓存它,直到整个文档准备好发送。
并且,客户端 AJAX 请求也将等待,直到整个文档在 运行 success
函数之前被接收。
因此,您需要在服务器上设置一些东西来存储进度,供您调用的另一个脚本使用。
您的服务器端脚本应该发回一个随机令牌,然后 continue processing php after sending http response。
然后您的客户端脚本将需要偶尔使用该令牌查询您的服务器,直到长期进程完成或失败。
您可以通过使用 WebSockets 更快地更新客户端,正如 Tuckbros 在评论中提到的那样(我很感谢提到我的服务器),但除非用户知道进程何时在几十秒内结束很重要毫秒,我建议保持正常 Web-PHP 和 AJAX,因为 WebSockets 需要对 CLI-PHP 和 HTTP 的额外细微差别有所了解。
我陷入了这个问题,关于在 php 上制作实时进度条(没有 php 推送器)
假设我有 10 行数据,这些数据将被插入到数据库中。
现在如何发送进度条数据,同时也插入到数据库中。
非常感谢您的回答。 谢谢
下面是我的代码示例:
// script.js (client)
// This function executed when user submit form
function store() {
// Listen Server Side Event
let event = new EventSource('controller/store')
event.addEventListener('message', response => {
// Then update progressbar
updateProgressbar(response.percent)
})
// Ajax to save data to database
$.ajax({
url: baseUrl + 'controller/store',
type: 'POST',
dataType: 'JSON',
data: $('#form').serializeArray(),
success: function(response) {
console.log(response)
}
})
}
// Controller.php (server)
public function store() {
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");
header("Connection: keep-alive");
$total_row = count($_POST['customer']);
for ($i = 0; $i < $total_row; $i++) {
usleep(100000);
$this->db->insert('customers', $_POST['customer'][$i]);
$percent = ($i + 1) * (100 / $total_row);
echo "event: message\n";
echo 'data: {"status": "loading", "percent": "' . $percent . '"}';
echo "\n\n";
ob_end_flush();
flush();
if (connection_aborted()) break;
}
echo "event: message\n";
echo 'data: {"status": "done", "percent": "' . $percent . '"}';
echo "\n\n";
}
Web 服务器和浏览器不会按照您想要的方式运行。
HTTP headers 包含内容长度,Web 服务器在将文档发送到客户端之前希望知道该长度。除非您已经确切知道文档 body 的长度,否则服务器将(通常)等到 PHP 脚本退出后再向客户端发送任何信息。
ob_end_flush()
和flush()
不直接向客户端发送信息;将它发送到 Web 服务器,它仍然会缓存它,直到整个文档准备好发送。
并且,客户端 AJAX 请求也将等待,直到整个文档在 运行 success
函数之前被接收。
因此,您需要在服务器上设置一些东西来存储进度,供您调用的另一个脚本使用。
您的服务器端脚本应该发回一个随机令牌,然后 continue processing php after sending http response。
然后您的客户端脚本将需要偶尔使用该令牌查询您的服务器,直到长期进程完成或失败。
您可以通过使用 WebSockets 更快地更新客户端,正如 Tuckbros 在评论中提到的那样(我很感谢提到我的服务器),但除非用户知道进程何时在几十秒内结束很重要毫秒,我建议保持正常 Web-PHP 和 AJAX,因为 WebSockets 需要对 CLI-PHP 和 HTTP 的额外细微差别有所了解。