Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active July 10, 2016 20:27
Show Gist options
  • Save Integralist/d84d65c909eeafe4dfca to your computer and use it in GitHub Desktop.
Save Integralist/d84d65c909eeafe4dfca to your computer and use it in GitHub Desktop.
Functional Programming: Polling XHR
define(['module/bootstrap'], function(news) {
var $ = news.$;
function seconds(secs) {
return secs * 1000;
}
function incrementDelay() {
// don't want the delay to become ridiculous so I set a threshold I don't want it to go beyond
if (delay < threshold) {
delay *= 2;
}
return delay; // we return a value for the sake of our `dispatch` method called by `checkStatus`
}
function exists(value) {
return value !== undefined && value !== null;
}
function dispatch() {
var fns = Array.prototype.slice.call(arguments, 0);
var size = fns.length;
return function(target) {
var ret;
for (var i = 0; i < size; i++) {
var fn = fns[i];
ret = fn.call(fn, target);
if (exists(ret)) {
return ret; // break out of the loop as we've executed a function that doesn't return null
}
}
return ret;
};
}
var checkStatus = dispatch(
function(status) { return status === 304 ? incrementDelay() : null; },
function(status) { return status === 200 ? delay = seconds(5) : null; }
);
function success(data, status, xhr) {
checkStatus(xhr.status);
poll(endpoint);
}
function failure(xhr, status, error) {
incrementDelay();
poll(endpoint);
}
function endpoint() {
$.ajax('http://localhost:3000/foobar', { timeout: limit }).then(success, failure);
}
function poll(endpoint) {
window.setTimeout(endpoint, delay);
}
var limit = seconds(5); // XHR timeout limit
var delay = seconds(5); // timer delay
var threshold = seconds(20); // timer delay threshold
poll(endpoint);
});
@danscotton
Copy link

This is much harder than I initially thought it would be! The asynchronous nature of the whole thing (both the timeouts and the ajax requests) makes it tricky, and it's hard trying to work out a way of not resorting to storing state in variables across the function calls.

I really like the small seconds and exists functions, and being able to compose your checkStatus method using dispatch seems nice and functional to me. I started trying to think how I would solve this using OO (https://gist.github.com/danscotton/6be0c64188ec1ac42111) to see if that'd help me develop things in a functional way but that didn't really help at all! The main thing I was trying to achieve was to keep the polling behaviour (delays and thresholds) separate from the ajax behaviour (requests, status codes, timeouts).

You don't seem to yield the data from a successful request anywhere either? Is the purposefully not a requirement or would you eventually have to slot that in too?

Here's my attempt at trying to remove the delay variable anyway, and passing it around in callbacks: https://gist.github.com/danscotton/828ee933b2afc0653db1. I just find that doing so litters most methods calls with the parameter, but this just might be my lack of understanding of writing functional code. Really need to read the functional js book! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment