Polling AJAX Using When.js with jQuery AJAX Promises
Abstract: Using when.js‘
poll
command together with jQuery’s Ajax methods yalst operator clients written in Javascript can define their data update loop with a minimal amount of code.
Contents
The Problem
The Principle Of Promises
A Promise-based interface provides a nice way to decouple the asynchronous internals of the network operation from the application program flow.
A general description is that a promise encapsulates the final result of an asynchronous operation. A promise may be in one of the three states,
"pending"
,"resolved"
, and"rejected"
. The promise itself accepts callbacks via itsthen
method.[2]
Which means that instead of specifying callback functions in the call of an asynchronous operation that operation simply returns a promise (so to speak a “promise” of its eventual result).
The advantage is that it is easy to compose new promises from existing ones. Examples are
- The combined promise
all
which resolves not until all given promises resolve (e.g. loading a bunch of images before displaying the slide show). - The competitive promise
any
which evaluates to the return value of the promise whichever one completes first (e.g. timing out an operation by combining it with a timeout promise) - The propagation/forwarding of promises by returning a new promise from a
then
callback. E.g. when polling Ajax in case the reason for an Ajax failure was a timeout condition theonRejected()
handler could resolve a newly created promise with a default value an return that promise. Thus the poll control loop is not interrupted.
Another advantage is that sequential chains of asynchronous logic actually appear sequential with promises rather than with the unwieldy nesting patterns of callback functions [5].
The Libraries
Browsing for other promise libraries the simple API of When.js [4] stands out. It’s features include
- important combinators like
map
,all
,any
,pipeline
,sequence
,parallel
,… - convenient utility promises like
timeout
,delay
andpoll
- coexisting with jQuery promises and
- transforming other callback-based APIs into promise-based APIs, e.g. when loading an image:
1 2 3 4 5 6 7 8 |
require(['when', 'when/callbacks'], function(when, callbacks){ var img = $('<img alt="" />'); var imagePromise = callbacks.call(img.on.bind(img, 'load', null, null)); imagePromise.then(console.log.bind(console, "Loaded")); img.get(0).src = "put image url here"; }); |
When.js’ Poll Method
The When.js poll
method will
“execute a
worker
task repeatedly at the specified intervalΔT
, until theshouldFinish
condition function returns true. TheresultPromise
will be resolved with the most recent value returned fromworker
. Ifworker
fails (throws an exception or returns a rejected promise) beforeshouldFinish
condition returns true, theresultPromise
will be rejected.” [4]
which is an excellent choice for wrapping the jQuery Ajax worker function for our purpose.
The Monitor Code
As “promised” here is the final code which defines the monitoring loop in the yalst operator console.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function ajaxWorker(){ return $.ajax(webServiceUrl, {dataType: 'json', timeout: 20000}) .then(null, function(xhr, status, httpErrorDescription){ if (status == "timeout"){ var dfd = new $.Deferred(); dfd.resolve(PollResult.timeout); return dfd.promise(); } }); } var polling = poll(ajaxWorker, intervalTimeout, function(pollResult){ return pollResult != PollResult.serverOverload; }); |