Let's build another kind of application that works in much the same way; one that uses functional programming to react to changes in state. But, this time, the application won't be able to rely on event listeners.
Imagine for a moment that you work for a news media company and your boss tells you to create a web application that tracks government election results on Election Day. Data is continuously flowing in as local precincts turn in their results, so the results to display on the page are very reactive. But we also need to track the results by each region, so there will be multiple objects to track.
Rather than creating a big object-oriented hierarchy to model the interface, we can describe it declaratively as immutable data. We can transform it with chains of pure and semi-pure functions whose only ultimate side effects are updating whatever bits of state absolutely must be held onto (ideally, not many).
And we'll use the Bacon.js
library, which will allow us to quickly develop Functional Reactive Programming (FRP) applications. The application will only be used one day out of the year (Election Day), and our boss thinks it should take a proportional amount of time. With functional programming and a library such as Bacon.js
, we'll get it done in half the time.
But first, we're going to need some objects to represent the voting regions, such as states, provinces, districts, and so on.
function Region(name, percent, parties){ // mutable properties: this.name = name; this.percent = percent; // % of precincts reported this.parties = parties; // political parties // return an HTML representation this.render = function(){ var lis = this.parties.map(function(p){ return '<li>' + p.name + ': ' + p.votes + '</li>'; }); var output = '<h2>' + this.name + '</h2>'; output += '<ul>' + lis.join('') + '</ul>'; output += 'Percent reported: ' + this.percent; return output; } } function getRegions(data) { return JSON.parse(data).map(function(obj){ return new Region(obj.name, obj.percent, obj.parties); }); } var url = 'http://api.server.com/election-data?format=json'; var data = jQuery.ajax(url); var regions = getRegions(data); app.container.innerHTML = regions.map(function(r){ return r.render(); }).join('');
While the above would be sufficient for just displaying a static list of election results, we need a way to update the regions dynamically. It's time to cook up some Bacon and FRP.