If you’ve ever downloaded a large video or installation file, you could always follow your progress on the download dialog:
Unfortunately, browsers aren’t able to update you on the progress of long-running processes that take place on the server – that is until they’re done. Meanwhile, you have no way of knowing if anything is in fact happening at all. A lot of people have tried to implement their own progress bar, but had varying degrees of success. Recently, the introduction of Server-Side Events (SSEs) have been a great step forward in this regard. In today’s article we’ll be taking a look at how to use SSEs to provide feedback and a progress bar for server-side processes.
Advertisement
Emulating a Long-running Process
The easiest way to make a script go on for a long time without actually doing anything is to run a loop. It also helps to free up processor time by calling a sleep function within the loop. PHP is a great language to use for the purposes of emulating a long-running process and it does indeed have a sleep() function. It accepts an integer specifying the number of seconds to sleep for. Hence, the following for loop will take about 60 seconds to complete and will send exactly 60 “processing…” messages to the client:
In my Receive Updates from the Server Using the EventSource article, I introduced Server-sent Events and their role in producing server pushes to the client. Under normal circumstances, the browser will maintain a connection to the script so long as it is running and does not issue a message to terminate. Combine that with a flexible ID-driven messaging system and you’ve got yourself an ideal way to send progress updates to the client. The best part is that with a little JSON encoding, we can send additional information as well as percentage numbers for the progress bar.
The following page is very much the same as the one from the EventSource article, with the addition of an HTML5 progress bar. Afterall, if a browser supports Server-sent Events, it probably also supports the new progress bar.
The JavaScript EventSource object provides an onmessage() event that we can bind to in order to receive communications from the server. These are held in the event parameter’s data attribute. Recall that it is a JSON-formatted string so we have to run the data through the JSON.parse() method before we can work with it. Once decoded, the message is logged to the results DIV and the progress is used to set the progress bar. I went a step further and display the actual percent value in a <span> element and continually update its width so as to move the number along with the progress bar meter.
The “CLOSE” termination signal is sent via the EventSource ID. On the client-side, it is stored in the event’s lastEventId property. Upon receiving the “CLOSE” EventSource ID, the communication channel is closed by the client and the progress bar’s value is set to it’s maximum to represent completion of the task.
var es;
functionstartTask(){
es = new EventSource('sse_progress.php');
//a message is received
es.addEventListener('message', function(e){
var result = JSON.parse( e.data );
addLog(result.message);
if(e.lastEventId == 'CLOSE') {
addLog('Received CLOSE closing');
es.close();
var pBar = document.getElementById('progressor');
pBar.value = pBar.max; //max out the progress bar
}
else {
var pBar = document.getElementById('progressor');
pBar.value = result.progress;
var perc = document.getElementById('percentage');
perc.innerHTML = result.progress + "%";
perc.style.width = (Math.floor(pBar.clientWidth * (result.progress/100)) + 15) + 'px';
}
});
es.addEventListener('error', function(e){
addLog('Error occurred);
es.close();
});
}
function stopTask() {
es.close();
addLog('Interrupted');
}
function addLog(message) {
var r = document.getElementById('results');
r.innerHTML += message + '<br>';
r.scrollTop = r.scrollHeight;
}
Here is a snapshot of the HTML code in Chrome produced by the SSE’s onmessage() event:
Results
on iteration 1 of 10 on iteration 2 of 10 on iteration 3 of 10 on iteration 4 of 10 on iteration 5 of 10 on iteration 6 of 10
60%
Advertisement
Conclusion
Though few and far between, there are some browsers that don’t support Server-sent Events or the Progress Element. We’ll consider some fallbacks for such older and non-compliant browsers in the next article.
Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.
JavaScript, also known as JS, was invented in 1995 and has been utilized in various programming fields since then. It is a high-level, yet lightweight,
PhpExcel's successor, PhpSpreadsheet, is a pure PHP library that provides a set of classes that allow you to read from and write to a variety of different
The original home of HTML tutorials. HTMLGoodies is a website dedicated to publishing tutorials that cover every aspect of being a web developer. We cover programming and web development tutorials on languages and technologies such as HTML, JavaScript, and CSS. In addition, our articles cover web frameworks like Angular and React.JS, as well as popular Content Management Systems (CMS) that include WordPress, Drupal, and Joomla. Website development platforms like Shopify, Squarespace, and Wix are also featured. Topics related to solid web design and Internet Marketing also find a home on HTMLGoodies, as we discuss UX/UI Design, Search Engine Optimization (SEO), and web dev best practices.
Advertiser Disclosure: Some of the products that appear on
this site are from companies from which TechnologyAdvice
receives compensation. This compensation may impact how and
where products appear on this site including, for example,
the order in which they appear. TechnologyAdvice does not
include all companies or all types of products available in
the marketplace.