Hi Expert!
I have a long running function. Which iterates through a large array and performs a function within each loop.
longFunction : function(){
var self = this;
var data = self.data;
for(var i=0; len = data.length; i<len; i++){
self.smallFunction(i);
}
},
smallFunction : function(index){
// Do Stuff!
}
For the most part this is fine but when I am dealing with arrays above around 1500 or so we get to the point of recieving a javascript execution alert message.
So I need to break this up. My first attempt is like so:
longFunction : function(index){
var self = this;
var data = self.data;
self.smallFunction(index);
if(data.slides[index+1){
setTimeout(function(){
self.longFunction(index+1);
},0);
}
else {
//WORK FINISHED
}
},
smallFunction : function(index){
// Do Stuff!
}
So here I am removing the loop and introducing a self calling function which increases its index each iteration. To return control to the main UI thread in order to
prevent the javascript execution warning method I have added a setTimeout to allow it time to update after each iteration. The problem is that with this method
getting the actual work done takes quite literally 10 times longer. What appears to be happening is although the setTimeout is set to 0, it is actually waiting more
like 10ms. which on large arrays builds up very quickly. Removing the setTimeout and letting longFunction call itself gives performance comparable to the original
loop method.
I need another solution, one which has comparable performance to the loop but which does not cause a javascript execution warning. Unfortunately webWorkers cannot be
used in this instance.
It is important to note that I do not need a fully responsive UI during this process. Just enough to update a progress bar every few seconds.
Would breaking it up into chunks of loops be an option? I.e. perform 500 iterations at a time, stop, timeout, update progress bar, perform next 500 etc.. etc..
Is there anything better?
ANSWER:
The only solution seems to be chunking the work.
By adding the following to my self calling function I am allowing the UI to update every 250 iterations:
longFunction : function(index){
var self = this;
var data = self.data;
self.smallFunction(index);
var nextindex = i+1;
if(data.slides[nextindex){
if(nextindex % 250 === 0){
setTimeout(function(){
self.longFunction(nextindex);
},0);
}
else {
self.longFunction(nextindex);
}
}
else {
//WORK FINISHED
}
},
smallFunction : function(index){
// Do Stuff!
}
All I am doing here is checking if the next index is divisible by 250, if it is then we use a timeout to allow the main UI thread to update. If not we call it again directly.
Please help me!
AVADHESH PATEL
03-May-2013