TriTarget

A blog of personal quality

The Pyramid of Doom: A javaScript Style Trap

DISCLAIMER: Using promises is a much better way to handle asynchronous situations. Use the advice in this post only as a last resort.

The term “Pyramid of Doom” was coined (as far as I know) from the JavaScript Jabber podcast episode 1: Asynchronous Programming.

In JavaScript that uses AJAX and other asynchronous methods they all take a function as a callback argument. A common yet ugly style to code this is using anonymous functions:

setTimeout( function() {
alert("Hello World!");
}, 1000);

Although these are quick and easy they can really get over complicated producing a ever increasing indent to the code. This has the effect of making a pyramid like shape out of the whitespace when you turn it on it side:

The Pyramid of Doom (pyramid.js)
// Code uses jQuery to illustrate the Pyramid of Doom
(function($) {
$(function(){
$("button").click(function(e) {
$.get("/test.json", function(data, textStatus, jqXHR) {
$(".list").each(function() {
$(this).click(function(e) {
setTimeout(function() {
alert("Hello World!");
}, 1000);
});
});
});
});
});
})(jQuery);

This leads to a difficulty in readability. It also confuses what is in scope and out of scope. A refactoring might included named functions that makes it easier to see what is happening and understand scoping.

Refactored Version to avoid the Pyramid (refactor.js)
// Code uses jQuery
(function($) {
function init() {
// Add onClick to buttons
$("button").click(getData);
}
function getData() {
$.get("/test.json", onSuccess);
}
function onSuccess(data, textStatus, jqXHR) {
$(".list").each(addListOnClick);
}
function addListOnClick(e) {
$(this).click(helloWorldTimeout);
}
function helloWorldTimeout() {
setTimeout(helloWorldAlert, 1000);
}
function helloWorldAlert() {
alert("Hello World!");
}
$(init);
})(jQuery);

Comments