I have to load a very big JSON object and perform various expensive processes. For this reason, I am showing a progress bar which increments a total of five times. If I have to load 10000 items, it will update every 2000 times, etc.
The problem is the effect is not visible because all the stack executes after the entire function is complete, instead of updating the progressbar at every 20% of the process. It doesn't matter if I try to load 10000 items or 2 million items, same stuff happens, and judging by the computation delay between console logs, there is definitely enough processing time to show a visible progress effect. Perhaps I'm not understanding the javascript for(I know this wasn't the way to do it). How do you track an expensive process and make a visible progress bar effect properly?
login with
username : admin
password: testit
var initItems = function(publicationItems) {
var publications = new Array();
var numberOfItems = goog.object.getCount(publicationItems);
var minStep = 20;
var currentProgress = 20;
var progressBarStep = parseInt(numberOfItems / 5);
var i = 0;
goog.object.forEach(publicationItems, function() {
var currentName = publicationItems.name;
var currentCat = publicationItems.categories;
// Insert clear div to break line after every 5 items.
if (i % 5 == 0 && i != 0)
publications.push(this.clear);
if(i % progressBarStep == 0)
{
progressBar.setValue(currentProgress);
console.log(i + ' ' + progressBarStep + ' ' + currentProgress + ' ' + progressBar.getValue());
currentProgress += minStep;
}
i++;
publications.push(goog.dom.createDom('div', {
'style' : 'width:' + this.currentPublicationDimension + 'px;height:' +
this.currentPublicationDimension + 'px;border:1px solid #B3B3B3;' +
'float: left;margin-top: 5px;background-color: #FCFCFC;' +
'max-width:' + this.currentPublicationDimension + 'px;max-height:' +
this.currentPublicationDimension + 'px;_height:' +
this.currentPublicationDimension +
'px;_width:' + this.currentPublicationDimension + 'px;margin-left:' +
this.publicationLeftMargin + 'px;',
'class' : 'publication'
}, currentName, currentCat));
}, this);
return publications;
};
And the context from where this function was called:
// Bind COMPLETE event listener to ajaxHandler.
goog.events.listen(ajaxHandler, goog.net.EventType.SUCCESS,
goog.bind(function(e) {
//goog.style.showElement(progressBarContainer, false);
goog.dom.append(this.mainViewPublications, initItems.call(this, e.target.getResponseJson()));
}, this), false, this);
The problem is that JavaScript is Singlethreaded and first tries to execute the calculations. The ProgressBar is asynchronous and will only update, if the thread is not busy.
You could use callbacks like following
function a () {
/* do one iteration */
progressBar.setValue(currentProgress);
goog.Timer.callOnce(a, 10);
}
The Problem with that, is that you can't pass parameters to the function and you have to use global variables (or at least 'object' wide variables).
I currently have the same issue and haven't found a really good solution. So this is a first approach. If I find another solution I will update it here.