I have a Livewire component that uploads a video to YouTube in chunks. While uploading, I want to update the progress bar on the frontend by dispatching Livewire events for each chunk uploaded. However, the issue is that all the dispatched events are received only at the end of the function execution, instead of being received in real-time as the upload progresses. Why is this happening, and how can I fix it?
Here’s a simplified example of my current implementation. The Component (YoutubeVideoUploader.php
):
class YoutubeVideoUploader extends Component
{
public function uploadVideo()
{
for($i = 0; $i < 10; $i++) {
$this->videoUploadProgress = $i;
$this->dispatch('uploadProgress', ['progress' => $i]);
Log::info("uploadProgress: " . $i . "%"); // this works well
sleep(1);
}
}
}
Blade Template (youtube-video-uploader.blade.php
):
<form id="videoUploadForm" wire:submit.prevent="uploadVideo">
<!-- some fields here and a submit button -->
</form>
<script>
document.addEventListener('livewire:init', () => {
Livewire.on('uploadProgress', event => {
const progress = event[0]?.progress ?? 0;
// init hours, minutes, seconds..
console.log(`[${hours}:${minutes}:${seconds}] uploadProgress event:`, progress);
});
});
</script>
2
Answers
IMO, every time you invoke
sleep(1)
in youruploadVideo
method, PHP will halt the execution of the currently running script for1 second
.The frontend will not receive the dispatched events in that time, so it seems events are
buffered
and fire all at once at the end of function execution.Try to Force Livewire and PHP to flush the data to the frontend by using
ob_flush()
andflush()
while the script is still running.i dont realy know what is the end use of this but i believe you want a visual clarification of how far the function is. This feat can be accomplished by using the livewire
stream
function in you componant this wil look like:And then you blade wil look something like this:
If you want the value in your javascript there is probably an event listener that can recognize the value change and will then retrieve the value. This wil be handy to do with an hidden
input
field. if this is what you want i can do more research and provide that within this answer. code example