Async Javascript, NodeJS and MongoDB rant 3 years ago

This site is running on NodeJS ( That is, it's running on a JavaScript web server. NodeJS (with the right middleware) is a joy to develop simple sites like this in. Maybe larger as well, but i have not had the chance to try it. Anyway, JavaScript solves the problem of asynchronous code by using callbacks. Which means that if you have a piece of asynchronous code, you must pass in a (anonymous) function as an argument which contains the code which is supposed to run afterwards.

var x = asyncMethod();
var y = asyncMethod2(x);
var z = asyncMethod3(y);

This piece of code above will run asyncMethod2 and asyncMethod3 directly. It will not wait for the previous asynchronous methods to finish. Pretty normal, expected behaviour. But we want to use the results from them in the next line (asyncMethod2 uses x etc). Some languages, like C#, solves this by introducing the await keyword, which can be used on async method calls, then the code which relies on the results will wait until the result is obtained.

This is how JavaScript does it:

asyncMethod(function(x) {
    asyncMethod2(x, function(y) {
        asyncMethod3(y, function(z) {

Not so bad... for a few layers. Asynchronous code and patters in all glory, but sometimes it becomes to complicated and intricate. The NodeJS driver for MongoDB is async. This means that the method producing this page has a lot of callbacks. Some methods on the driver (e.g. find() returns a Cursor-object which has the wonderful toArray() method which makes the code synchronous.) This is fine for me. I don't need enterprisey cool async code for serving some text and pictures on a simple personal homepage. I understand and know it is necessary and good for bigger projects. I like async code. But async code in the right context. And i have had few problems with it. But today i wanted to do a distinct() call on my blog collection in MongoDB. That method does not have a toArray() method and therefore is purely async. This means that i serve the page before i collect all the categories i have (I want to display blog post categories for filtering). Googling suggests that i should download and use some "async" framework with another framework "curry" which makes the "async" framework not look horrible or use more callbacks and setTimeout to hack my way around it. This is bad. I just want to get some stuff from MongoDB and wait for the results before serving the page. It should be simple. I should not need to download two more frameworks to do that.

So what did i end up doing? Well, the code is very much idented now, and there are lots of callbacks. I guess i have to live with it. There ought to be a synchronous mode in the driver though. Would make the code much cleaner. And since this isn't Amazon with thousands of request every second it would probably not affect response time.

Tweet about this post