I’m forgetting the async/sync stuff from before in favor of thenables. Deferred and its more polite personality, promise. There are just certain things that I think would be really tough to do with a callback architecture.
Normally, if I were showing a view of something I wouldn’t $.get() it from the server until my DOM is loaded, because I can’t do anything with the response until I’ve got elements to manipulate. But with jQuery’s implementation of AJAX calls, which return a promise, I can set it up so that I get data as soon as the Javascript is loaded and guarantee that I don’t try to move the data to DOM elements until it’s ready, too.
var mydata = $.get (window.location.origin + ":8080/foobar");
$( function () {
mydata .done (showdata);
});
function showdata (data) {
$( 'ul#something') .html (
_.map (data, function (row) {
return '<li>' +row.name +'</li>';
}) .join ( '' ) );
}
If data looked like [{“name”:”john”},{“name”:”bob”},{“name”:”fred”},{“name”:”alice”}], then our <ul> now looks like
<ul id="something"><li>john</li><li>bob</li><li>fred</li><li>alice</li></ul>
I think that’s slick. showdata won’t get called until the DOM’s loaded and we have the data, but there’s no waiting before we ask for it from the server. We use map() to output an array of HTML strings (instead of concatenating), then join those and put the output into $(‘ul#something’). There’s only one variable used — which is a very good thing, BTW, lots of variables is a code smell, IMO.
Another nice pattern I use:
Imagine this jQuery GET for some set of choices within a “topic”
var topic_data = $.get (
window.location.origin + ':8080' + '/topic/' + some_criteria);
{"name":"foobar","choices":["bob","fred","alice"]}
And separate documents for a user’s choice for that topic, which are referenced by the “name” of the topic. In other words, I had to get that topic to find the key to use for the next GET. I need to render the topic_data in showTopicChoices regardless of what happens in that GET.
topic_data .done (showTopicChoices, function (topic) {
$.get (window.location.origin + ':8080' + '/user/topic/' + topic.name)
.done (overlayUserChoice);
});
It’s a nice way to separate the rendering of more general data from other indicators.