如何在没有 PHP Pusher 的情况下制作实时进度条

Posted

技术标签:

【中文标题】如何在没有 PHP Pusher 的情况下制作实时进度条【英文标题】:How To Make Realtime Progressbar Without PHP Pusher 【发布时间】:2021-10-16 02:17:25 【问题描述】:

我陷入了这个问题,关于在 php 上制作实时进度条(没有 php pusher)

假设我有 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";

【问题讨论】:

我根本不知道“PHP Pusher”是什么,但是除了服务器服务器端语言之外,您已经使用三种可用于执行此操作的技术对其进行了标记。你能把重点放在更具体的事情上吗? @ChrisHaas 在这种情况下,我使用 php(服务器)和 javascript(客户端)。我尝试使用 AJAX 插入数据并使用服务器发送事件显示进度条。问题是:AJAX 需要 JSON 作为响应,同时 SSE 需要 Event-Stream 作为响应。 HTTP 只能接受 1 种类型的响应。 这仍然需要更多解释,您要解决的更大的问题。进度条是否返回到正在发送数据的客户端;还是给其他客户?它是否一次发送所有 10 行数据,但每一行都需要很长时间才能插入数据库?还是一次发送一行? AJAX 不需要 JSON,它只是一个常见的约定。是客户发起了这个过程,还是只是被告知了它?进度条是字面的,还是只是“2:10”或“20%”或类似的文本? 这取决于你,如果没有关于服务器端可用内容的更多信息,你可以执行定期 ajax 请求来检查给出状态的 php 页面,你必须找到方法来做到这一点服务的 php 页面收集状态信息以及如何使用其响应来更新您的客户端页面。如果您对 websocket 感兴趣,也可以使用 php 完成,但您必须设置一个“专用”服务器(当前服务器的不同进程)。用php我喜欢这个ghedipunk on github 【参考方案1】:

Web 服务器和浏览器不会让它按照你想要的方式工作。

HTTP 标头包含内容长度,Web 服务器在将文档发送到客户端之前需要知道该长度。除非您已经确切知道文档正文的长度,否则服务器(通常)会等到 PHP 脚本退出后再向客户端发送任何信息。

ob_end_flush()flush() 不直接向客户端发送信息;将它发送到 Web 服务器,它仍然会缓存它,直到准备好发送整个文档。

而且,客户端的 AJAX 请求也会等到整个文档都被接收到之后再运行success 函数。

因此,您需要在服务器上设置一些东西来存储进度,以便您可以调用另一个脚本。

您的服务器端脚本应该发回一个随机令牌,然后是continue processing php after sending http response。

然后,您的客户端脚本将需要偶尔使用该令牌查询您的服务器,直到长期进程完成或失败。

您可以使用 WebSockets 更快地更新客户端,正如 Tuckbros 在 cmets 中提到的那样(我很欣赏提到我的服务器),但除非用户知道进程何时在几十毫秒内结束很重要,我建议继续使用普通的 Web-PHP 和 AJAX,因为 WebSockets 需要对 CLI-PHP 和 HTTP 的额外细微差别有所了解。

【讨论】:

以上是关于如何在没有 PHP Pusher 的情况下制作实时进度条的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 在没有 NPM 的情况下安装 echo 和 pusher js

如何在 pusher 的帮助下使用 websocket 从数据库中获取数据?

如何使用 PHP 绑定到 Pusher / Websocket 通道?

Pusher:在 App\Events\Event 的 testChannel 上没有回调

如何使用 RSpec 测试 WebSockets(使用 Pusher)?

广播的 Laravel 通知不会在前端实时显示,而是通过 Pusher 发送并显示在控制台中