Handling Callbacks with a Depth-First Tree in JavaScript

One of the hardest things to do in JavaScript when working with complex data structures and a callback oriented platform is to know for sure when all of your callbacks have been fully executed. This issue came to light when working with a MongoDB datastore that was being used to store an infinitely-deep nested menu structure.

This menu structure could be visualized as being a tree. In order to get the all of the needed menu items from this tree, a depth-first traversal of the tree was determined to be the easiest to track. Since I typically try to write the least amount of code possible to solve a problem, I started out with a set of simple callbacks that worked perfectly as long as there was only one menu-item that had any children. As soon as I had multiple children to traverse, the timing of the execution of the final callback happened well before it should have as well as occurring again at the correct time, causing some unexpected results.

I am sure that there are many ways to solve this particular issue that have some elegant algorithmic roots, I am trying to use the simplest method possible. In fact, there is a library that was originally written for use with NodeJS the solves this exact issue. The async library allows you to use async.each(array, iterator, callback);, which will call the iterator function for each member of array, and the iterator function should handle any necessary processing, calling the callback function when complete. If any of the instances of iterator throw an error, the other instances are short-circuited. If they all run to completion, the callback function passed in will be called only when all have completed successfully, greatly simplifying the logic.

A simple example with Mongo and recursion would be:

function loadMenu(element, index, array, done) {
    menu.model.find().exec().then(function (menus) {
        //Do Stuff Here...
        async.each(menus, loadMenu, done);
    });
}

async.each(menu, loadMenu, done);

Related Posts

May 14, 2014
2 minutes

Responsive Images with Picturefill 2.0

Responsive Web Design seems to be the way that the majority of websites will be developed in the near future. For a while, everyone was creating a separate website that catered to mobile devices in addition to the main website that desktop browsers were able to access. Web Developers and UX Designers quickly discovered that this was a less than ideal approach as it required maintaining two separate websites, and the mobile website tended to remove data that was visible on the desktop version of the site.

Jan 9, 2015
3 minutes

Authorize.Net Directpost is Overly Complex

One of the necessary evils that every ecommerce website that wants to accept credit card transactions must deal with is some sort of payment processing company. It just so happens that Authorize.net is one of the largest payment processors around, and they allow you to choose from a few different ways to integrate their payment processing functionality into your website. One of their ways is via DirectPost, which allows an eCommerce website to process a credit card transaction without the credit card information ever being sent through the website’s servers.

Mar 5, 2015
2 minutes

Don't Be a Dunce, Save Your Orders

There are some gotchas that you think that you will always see coming. One such gotcha is the need to save an object to the datastore to persist any changes you may have made to that object.

While it seems like a reasonable concept at the base level, there are times that the need to save an object completely escapes your mind. It seems that for many non-developers, this occurs when they have been working a long time on a file, typically a Microsoft Word document, shortly before their computer blue screens, losing all of their work.