To interaction with the dtime API via Javascript, you need to be able to chain together API calls in a straightforward manner.
Hypermedia APIs rely on state machine logic - given a current state, there are a number of transitions you can make (Valid HTTP verbs on the available rels)
In the code, transition(current_state, rel, opts)
is our way to transition.
where opts has some properties:
opts.uriVariables
: optional variables to go into a uri template.opts.data
: optional data to send with requestopts.method
: which http method to use (maybe default get)opts.success
: callback to attach on success, takes in the json responseopts.error
: callback to attach on error, takes in the json response
transition will internally use ajax_call(url, method)
to make the initial ajax
call. The below method will work with both jquery and zepto. For other options, you'd
need to change $.ajax to whatever format your XHR requests usually take.
transition internally relies on the href_for
function, you pass the current_state
variable in and find the link from that state object.
href_for(current_state, rel, uri_variables)
Href for loops through current_state._links and finds the link with a name == "rel" It uses uri template syntax to turn /questions/{question_id} into /questions/foo, if uri_variables.question_id = "foo".
In 1.5, jQuery introduced deferred objects - for chaining together multiple api calls, it's a really handy pattern. Read more about them here - http://api.jquery.com/category/deferred-object/
The above code uses a simple library to duplicate jquery deferred functionality: https://github.com/sudhirj/simply-deferred
It's an optional way to help clean up the way callbacks are chained together:
transition a, "b", success: (b)->
transition b, "c", success: (c)->
console.log(c)
vs
transition(a, "b").done (b)->
transition(b, "c").done (c)->
console.log(c)
The added benefit is that multiple done functions may be chained onto a deferred object, and that deferred object can even have done functions called on it after it's succeeded - those done callbacks will just immediately fire.
You can see this pattern used in the load_root()
function, and the load_sitemap()
function. These
functions allow you to make one AJAX request for the sitemap to service any number of requests, by
just chaining more done functions onto load_sitemap().done()
Deferreds also allow pipe
:
transition(a, "b")
.pipe((b)-> transition(b, "c"))
.done((c)-> console.log(c))
Which enforces the order of multiple ajax calls in the order they are piped.