Imagine you have several asynchronous calls that you need to make and you need to delay the execution of some task(s) until after all of the calls have completed.
Two of my OSS projects, anvil.js and cartographer.js, each deal with this use case in cascading situations. It's been "fun" coming up with ways to solve those in a re-usable manner and I thought I'd share a little bit about the learning experience.
TL;DR?
There really isn't one for this post, but let me tell you what I'm going to tell you. First I'll briefly describe Fork/Join, look at a simple implementation and use case. Then I'll show how partial application can take complex calls and reduce the arity requirement to fit with our existing forkJoin call. To end it, I'll create a slightly more realistic example that's more in-line with real-world uses of the pattern.
Fork/Join
In languages/runtimes where parallel execution is possible, the fork/join pattern provides your program with the ability to spin up multiple threads/processes to perform the work simultaneously1 while either blocking execution or not invoking some callback until all work has completed.
In JavaScript, while you can model concurrency, you don't have true parallelism2 and there is no way to block the main line of execution while other code runs. Instead what you can do is make several asynchronous calls and then invoke a callback once all of them have completed.
Plain English:
The problem we're solving for is how to delay execution until after several asynchronous calls have completed.
Simple Implementation
var forkJoin = function( queue, onComplete ) {
var results = [],
count = 0,
i = 0,
done = function( result ) {
if( result != undefined ) {
results.push( result );
}
if( --count === 0 ) {
onComplete( results );
}
};
if( queue == undefined || queue.length === 0 ) {
onComplete( [] );
} else {
count = queue.length;
for( i = 0; i < queue.length; i++ ) {
queue[ i ]( done );
}
}
};
Explanation
The queue is a list of functions which take a callback to invoke with their result when they have completed. The onComplete function is simply the callback to invoke with all the results we collected once all the work has completed.
The done function is the callback that we will pass into each worker function in the queue. When the worker finishes its task, it will invoke the done function with its result. Every time the done function is invoked, it decrements the count variable which represents the total number of out-standing calls to be completed. If the count reaches 0, then all the tasks have completed and we can invoke the onComplete callback with the results collected from the workers.
In Action (contrived example)
var call1 = function( onDone ) {
window.setTimeout( function() { onDone( 1 ); }, 20 );
};
var call2 = function( onDone ) {
window.setTimeout( function() { onDone( 2 ); }, 50 );
};
var call3 = function( onDone ) {
window.setTimeout( function() { onDone( 3 ); }, 30 );
};
forkJoin( [ call1, call2, call3 ], function( result ) {
console.log( result.toString() );
} );
This example should print some permutation of the numbers 1, 2 and 3 ( probably 1, 3, 2 ) after about 50 miliseconds. You can see an example of this in the jsFiddle:
That's all well and good, but it's not terribly practical … yet.
Making Things A Bit More Interesting (Partial Application)
Partial application allows us to reduce the number of arguments required (arity) to invoke a function by wrapping the call to the original function with specific argument values inside an outer function that will pass through some subset of arguments to the original call.
Contrived Partial Function Application
var original = function( one, two, three ) {
console.log( Array.join( [ one, two, three ], " " ) );
};
var partial = function( adjective ) {
original( "hello", adjective, "world" );
};
partial("cruel"); // will print "hello cruel world"
Um … What?
The reason we're looking at this is that the forkJoin function above only knows how to invoke functions with an arity of 1. Using partial function application, we can provide forkJoin with a function of reduced arity and still ensure that our original functions are called with the correct arguments.
Partial Application In Action
var call = function( value, delay, onDone ) {
window.setTimeout( function() { onDone( value ); }, delay );
};
var call1 = function( onDone ) {
call( 1, 20, onDone );
};
var call2 = function( onDone ) {
call( 2, 50, onDone );
};
var call3 = function( onDone ) {
call( 3, 30, onDone );
};
forkJoin( [ call1, call2, call3 ], function( result ) {
console.log( result.toString() );
} );
This produces the same result as the example above. The point here is that we're able to call more complex functions but expose them as a simple function that only takes the callback from forkJoin.
Let's Get Real
Up to this point, this post has been a bit dry and academic (but without all the helpful detail and precision you'd expect from a real academic write-up). So let's try and create code that's much closer to something you'd actually encounter and use in a web application.
Scenario
I need to make 2 different REST calls to a server API before rendering a response to the page. I only want to render the markup after all the calls have completed. Furthermore, I want to set a timeout on each call so that the request aborts and I get some default result.
Tools
I'm going to use jQuery's ajax call for making very simple server requests. The fiddle will use appendTo's mockJax library to intercept the requests and provide responses so that the code actually works without a server. Last, I am using Cartographer to render the results as markup that I can put on the page.
Code
// perform the actual call
var request = function( url, limit, fallback, onDone ) {
$.ajax( {
url: url,
timeOut: limit,
success: function( data ) {
onDone( data );
},
error: function() {
onDone( fallback );
}
} );
};
// create a partial application for the GitHub profile request
var getGitHubProfile = function( onDone ) {
request( "http://api.github.com/users/arobson",
1,
{
// content here omitted for brevity
},
onDone );
};
// create a partial application for the Twitter profile request
var getTwitterProfile = function( onDone ) {
request( "https://api.twitter.com/1/users/show.json?screen_name=A_Robson",
1,
{
// content here omitted for brevity
},
onDone );
};
// create a map function for the profile template
cartographer.map( "profile" );
// make the calls and render a template with the data when all calls are complete
forkJoin( [ getGitHubProfile, getTwitterProfile ], function( data ) {
var profile = $.extend( {}, data[0], data[1] );
cartographer.render( "profile", "test", profile, function( id, markup, op ) {
$("#placeholder").hide().fadeIn( 300 ).html( markup );
} );
} );
This is only a portion of what's in the fiddle, but it's the part that really matters. The request function is where the work is actually getting done, but there's not a clean way to provide the arguments from the forkJoin call itself. The solution demonstrated here is to use partial application to reduce the arity for forkJoin.
Once we've received a response from each request, our callback is invoked with the list of results. These results are then being merged together using jQuery's extend.
The cartographer lines are creating a template from a DOM element and then rendering markup based on the merged JSON responses from the server.
Fiddle
Summary
I hope this post was interesting. If there are improvements, please make a comment and I'll try to get the source and fiddles on the page updated with thanks and mention of your contribution. I'm certainly not an expert but I've really enjoyed what using this pattern has enabled me to accomplish so far.
Notes
1. At least as much as the system will allow given hardware and load constraints
2. Ok, so you *could* use web-workers or the up-coming stuff in Node but … don't
I have been working on a templating engine that uses only valid HTML to define the templates. It uses simple conventions in order to produce markup from JSON and a template. The world doesn't need another templating language. But I want a different solution than the ones that exist. This post is as much about why as it is about what.
TL; DR
I made a thing. You can see the code on GitHub and see the humble beginnings of the docs for it here. If you do read the whole thing, just imagine it started as an elevator pitch but the elevator broke and you're going to be stuck with me for quite some time…
Disclaimer
Developers have worked hard to create templating approaches that are performant, viable solutions. My criticism of certain aspects of those solutions isn't criticism of individuals or their ability. I'm just super particular. Let's take a moment to laugh at me:

There's An Amazing DSL For Describing UI
It's called HTML. It's not the new hawtness. The DOM has and will continue to hurt feelings and crush dreams. On the upside, there is something nice about clean HTML that is unmarred by odd-ball, proprietary magic strings that mean something to a pre-processor. Don't get me wrong, I love arbitrary spin-off syntax just as much as everyone else, but sometimes it's nice to stick with open standards that are well known across the industry.
You Got Your Egg Nog In My Goat Milk!
I guess my primary complaint with the predominant approach is the rampant abandon with which imperative and declarative styles; markup and source are blended into a hard to cypher, tightly coupled mass of untestable concerns.
I dream of a world where templates look like this:
<ul data-id="people">
<li><span data-id="firstName"></span> <span data-id="lastName"></span></li>
</ul>
and not like:
<ul>
{{#each people}} // srsly? I have to tell it to iterate?
<li>{{firstName}} {{lastName}}</li>
{{/each}} //lulz, it doesn't know when it's done…
</ul>
or like:
<ul>
<% for ( var index = 0; index < people.length; index++){ %>
<li><%= people[index].firstName %> <%= people[index].lastName %></li>
<% } %>
<ul>
// are your eyes screaming too?
All About Trade Offs
Whining and snark aside, each approach is making the choice to accept some drawback in order to obtain specific advantages and features. Most of the traditional template engines compile the template into a function that can be parameterized and invoked. This approach sacrifices testability and separation of concerns to get speed and the ability to embed logic and adaptability into the template.
I am willing to sacrifice a little speed and adaptability in the markup in order to reinforce testability, adhere to standards and keep my solution clean and maintainable.
Why Meet What
I started writing Cartographer about 5 months ago and it's gone through a lot of major changes in that period of time. It still has a way to go, but in the end, Cartographer's main goal is to provide a convention based, HTML 5 templating engine that's simple to use yet powerful and flexible. It's never going to run as fast as say, Transparency, but a refactor to improve the performance by a little over 100% and reduce the number of dependencies is in the works (and Transparency uses classes for binding and will never hold a candle to Cartographer's feature set).
Basics
Cartographer does not render markup onto the page. It invokes your callback with the markup and a small bit of metadata about the markup so you don't have to try and track the context of the original call yourself. Cartographer is asynchronous only. It will never have a blocking implementation. This is skipping ahead a bit, but the reason is primarily because nested templates could get specified and loaded in at any point during the generation of markup.
Once a template has been created, you can choose to generate additions to the original markup or render specific portions of the original markup. This means you can define a parent template that may be a composite of several templates but generate any portion of that template with new model fragments and then choose how and when to put that new fragment on the screen.
// create a template
Cartographer.map(templateName);
// generate markup from template
Cartographer.render(templateName, id, markup, function( id, markup, operation ) {
// id is the template's id
// markup is the generated content
// operation is either "render", "update" or "add"
});
Cartographer has a few advanced features that allow it to do things that other JS template engines don't (or can't). So here's a few to give you an idea.
Where Do Templates Come From?
Templates can come from any source. Out of the box, Cartographer looks in the DOM for the template and then asks infuser for the template. You can provide your own methods for getting templates and control when they get checked by either appending or prepending them to Cartographer's list of template sources.
// This appends this source to the end of sources Cartographer will check first
Cartographer.resources.appendSource( function( templateName, onSuccess, onFail ) {
// check for the template
// if you have it, call onSuccess with the text content
// otherwise call onFail()
});
// This prepends this source to the end of sources Cartographer will check first
Cartographer.resources.prependSource( function( templateName, onSuccess, onFail ) {
// check for the template
// if you have it, call onSuccess with the text content
// otherwise call onFail()
});
Combining Templates From Markup
A template can specify that another template should be used in place of an element by setting the data-template attribute:
<div data-id="person">
<!-- this span element will not be included in the final markup -->
<span data-template="person-details"></span>
</div>
Combining Templates From Model
A model can choose to have a different template render any portion of it (even including values) by adding a __template__ member.
{
"firstName": "Alex",
"lastName": "Robson",
__template__: "simple"
}
When you need a template for a value, it's a bit more complicated because you need to communicate both the value of the property and the template. This requires changing the value to a hash that includes value and template:
{
"height": "6'10\"",
"weight": { __value__: 254, __template__: "pounds" }
}
Is it more work? Absolutely. In this case, probably too much work. It'd be nicer if there were a way to use a function for that kind of case…
Fun With Functions
Which is why you can. Instead of letting you embed code in your template, Cartographer only allows code in your code. The Xzibit "Yo Dawg" meme writes itself:
{
"firstName": "Alex",
"lastName": "Robson",
"fullName": function() { return this.firstName + " " + this.lastName; }
}
Sure, it's not JS in your HTML (or vise versa) but it's not like I have to explain how this works. Best of all: you. can. test. this. approach.
But wait, there's MOAR!
Anything in the model that I've shown you can also have a function. So just imagine…
{
"height": "6'10\"",
"weight": {
__value__: 254,
__template__: function() {
if( this.weight > 250 ) {
return "pounds-warning";
}
else {
return "pounds-healthy";
}
}
}
}
Ok, so before you nerd-rage, I am not suggesting the whole function body belongs IN the model, you can just put the function handle there and define it elsewhere.
Status
Cartographer is alpha-ware. It has tests and what-not. I'm interested in feedback from people who are actually interested in using it and would be happy to know if it's helpful. If not, I've learned a lot working on it and will use it in future pet projects of mine.
Too Many Words
If you haven't decided to climb through the ceiling tiles and try your luck climbing out of the elevator shaft, there are places to go from here. Checkout the code, look at the docs (there's a complete running example on the main page) and ping me via Twitter or my GitHub. The project even has issues so you can make requests or notify me of all the broken stuff.
Pain is Opportunity
When I first decided to dive into a few Node.js and JavaScript projects, I was frustrated by how little guidance and convention I found in structuring, building and testing these kinds of projects. A lot of what I found seemed like lots of copy and paste solutions that would require several minutes of tweaking between projects. While I did stumble upon Require.js and Ender, neither of these addressed all the things I was concerned about and both were very prescriptive and really only handled one type of solution.
First Big CoffeeScript Project
So I set out to write a tool that would
- Generate a project scaffold
- Combine .js and/or .coffee files into build output in a predictable way
- Run lint against the output scripts
- Uglify each output script
- Gzip each output script
- Be capable of producing different outputs based on different build configurations
- Generate HTML scaffold for integration tests
- Host some form of test runner
- Continuously “build” in the background on file changes
As of several minor versions ago, Anvil is self-built and comes with a few additional features not listed. I’ve found that I can spin up projects very quickly and have running tests in no-time.
Screen Cast
Rather than make you read how easy it is to get started with Anvil, I thought it might be nice to do a screen cast and **show** you how simple it is.
An Intro To Anvil.js from Alex Robson on Vimeo.
Hope you enjoy!
