Last active
July 10, 2016 20:27
-
-
Save Integralist/d84d65c909eeafe4dfca to your computer and use it in GitHub Desktop.
Functional Programming: Polling XHR
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
andexists
functions, and being able to compose yourcheckStatus
method usingdispatch
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! :)