Browser Limits
Callstack size limit
Long-running script limit
100ms
Yielding with Timers
var button =document.getElementById("my-button");
button.onclick =function(){
oneMethod();
setTimeout(function(){
document.getElementById("notice").style.color= "red";
},250);
};
var button = document.getElementById("my-button");
button.onclick = function(){
oneMethod();
setTimeout(function(){
document.getElementById("notice").style.color = "red";
}, 50);
anotherMethod();
};
If anotherMethod() takes longer than 50 millisecondsto execute, then the timer code is
added to the queue before the onclick handler isfinished. The effect is that the timer
code executes almost immediately after the onclickhandler has executed completely,
without a noticeable delay.
Timer Precision
15ms
Setting timer delays of less than 15 can cause browser locking in Internet Explorer, so the smallest recommended delay is 25 milliseconds (which will end up as
either 15 or 30) toensure a delay of at least 15 milliseconds.
Array Processing with Timers
function processArray(items, process, callback){
var todo = items.concat(); //create a clone of the original
setTimeout(function(){
process(todo.shift());
if (todo.length > 0){
setTimeout(arguments.callee, 25);
} else {
callback(items);
}
}, 25);
}
Splitting Up Tasks
function multistep(steps, args, callback){
var tasks = steps.concat(); //clone the array
setTimeout(function(){
//execute the next task
var task = tasks.shift();
task.apply(null, args || []);
//determine if there's more
if (tasks.length > 0){
setTimeout(arguments.callee, 25);
} else {
callback();
}
}, 25);
}
function saveDocument(id){
var tasks = [openDocument, writeText, closeDocument, updateUI];
multistep(tasks, [id], function(){
alert("Save completed!");
});
}
Timed Code
function timedProcessArray(items, process, callback){
var todo = items.concat(); //create a clone of the original
setTimeout(function(){
var start = +new Date();
do {
process(todo.shift());
} while (todo.length > 0 && (+new Date() - start < 50));
if (todo.length > 0){
setTimeout(arguments.callee, 25);
} else {
callback(items);
}
}, 25);
}
Timers and Performance
The take away from Thomas’s research is to limit the number of high-frequency repeating timers in your web application. Instead, Thomas suggests creating a single repeating timer that performs multiple operations with each execution.
Web Workers
var worker = new Worker("code.js");
worker.onmessage = function(event){
alert(event.data);
};
worker.postMessage("Nicholas");
//inside code.js
self.onmessage = function(event){
self.postMessage("Hello, " + event.data + "!");
};
Loading External Files
//inside code.js
importScripts("file1.js", "file2.js");
self.onmessage = function(event){
self.postMessage("Hello, " + event.data + "!");
};
Practical Uses
var worker = new Worker("jsonparser.js");
//when the data is available, this event handler is called
worker.onmessage = function(event){
//the JSON structure is passed back
var jsonData = event.data;
//the JSON structure is used
evaluateData(jsonData);
};
//pass in the large JSON string to parse
worker.postMessage(jsonText);
//inside of jsonparser.js
//this event handler is called when JSON data is available
self.onmessage = function(event){
//the JSON string comes in as event.data
var jsonText = event.data;
//parse the structure
var jsonData = JSON.parse(jsonText);
//send back to the results
self.postMessage(jsonData);
};