I did a bit of frontend work for internal tools recently and chose to go with clojurescript, for obvious reasons.

Like clojure, clojurescript supports macros which let you express common lengthy idioms. I use the jayq library to interact with the browser since JQuery is the de-facto standard and battle tested.

A standard call to a JSON get in JQuery looks like this:

$ . getJSON ( 'ajax/test.json' , function ( data ) { doSomethingWith ( data ); });

Which is really a call to:

$ . ajax ({ url : 'ajax/test.json' , dataType : 'json' , success : function ( data ) { doSomethingWith ( data ); } });

Now when using jayq this would translate to:

( ajax "ajax/test.json" { :dataType "json" :success ( fn [ data ] ( do-something-with data ))})

This is just as simple, but a bit lacking in terms of readability, with a simple, add to this that you might want to check the done status of the resulting future and you end up with:

( let [ ftr ( ajax "ajax/test.json" { :dataType "json" :success ( fn [ data ] ( do-something-with data ))})] ( .done ftr ( fn [] ( refresh-view ))))

Thankfully, with macros we can make this much prettier, with these two simple macros:

( defmacro when-done [ ftr & body ] ` ( .done ~ ftr ( fn [] ~@ body ))) ( defmacro with-json [ sym url & body ] ` ( jayq.core/ajax ~ url { :dataType "json" :success ( fn [ data# ] ( let [ ~ sym ( cljs.core/js->clj data# )] ~@ body ))}))

We can now write:

( when-done ( with-json data "ajax/test.json" ( do-something-with data )) ( refresh-view ))

Which clearly turns down the suck on the overall aspect of your callback code.

There’s a lot more to consider of course, as evidenced by this PR, but it’s a good showcase of clojurescript’s abilities.