Meta Broadcast

we write about the things we build and the things we consume

node keeps us on track

Last time I gave an overview to why Metabroadcast used Node for some projects. Today I’m going explore moving an internal project, named the 'Internal Dashboard', from front to back-end code and some of the things we learnt about using an event driven language for synchronous actions.

front to back

The Internal Dashboard is essentially a status board, informing us Metabroadcats of who’s got how many issues to do, in progress or completed for the given iteration, what the latest commits and tweets were and alerts if a server or deploy fails. We use the Jira, Jenkins, Github, Bitbucket, Nagios and Twitter API’s to get all the data we need, sometimes making multiple requests to each API .At the beginning we thought "hey, it’s a few API calls, we can do this in the front-end right?", wrong. Overall we were making ~50 AJAX requests, splicing the results from different APIs together and finally updating the UI, all within the browser every minute or so. While browser Javascript implementations are much faster then a few years ago, they still have their limits so we decided to move things server side.

adapting to the server

Node was the obvious choice as the API 'adapters' I’d written for the front-end version could be easily transfered over to the back-end with minimum fuss. All that was needed was conversion to the CommonJS format, allowing the prototypal objects to be exported, and to move from jQuery ajax requests to Restler rest calls! Server to server really increases request speeds and keeps authentication credentials securely hidden, previously an issue when using user facing Javascript. As Node doesn’t have to manage memory between processing and UI updates, it also allowed quicker data manipulation, memory storage to show data instantly when a client connects, the requirement to only have to send API requests once for multiple clients and the use of websockets (socket.io specifically) to broadcast data to all web clients in parallel.

synchronise the asynchronous

Moving to server-side Javascript didn’t solve all of our problems though. While things were quicker, we still had to force synchronous API requests to ensure we received everything in order. For example, everything relied on Jira components so firing a request to both Jira and Jenkins simultaneously would cause errors if Jenkins responded first. To ensure this wasn’t a problem I made all modules utilise callbacks, nesting dependencies within. As mentioned before some modules needed to handle multiple requests to the same API. I needed to ensure the module callbacks were synchronous, even when the requests within didn’t need to be, therefore I developed a quick module (below) that accepts how many events you expect to happen and a function to run once all events have been triggered, as arguments. For subsequent projects we improved the way we deal with synchronous requests, utilising a queuing system, created by pushing functions to array, then executing them in order.

var ReadyListener = function(itemLength, fn){
    this.itemLength = itemLength;
    this.haveItems = 0;
    this.fn = fn;
};
ReadyListener.prototype.add = function(name){
    console.log('	'+name+': Ready');
    this.haveItems++;
    this.haveAllCheck();
};
ReadyListener.prototype.haveAllCheck = function(){
    if(this.haveItems === this.itemLength){
        this.fn();
    }
};
/**
 * Usage
 */
var rl = new ReadyListener(lengthToAimFor, function(){
    // To run once length has reached lengthToAimFor
});
// Do something with callback function
doSomething(function(){
    rl.add('Done Something');
});

Think we can do something better? Have thoughts about managing synchronous actions with Javascript? Let us know!

blog comments powered by Disqus
hiring makers: 8 positions Creative Technologist | Designer at Large | Software Engineer | Systems Engineer >> JOIN US
metabroadcast

reading others