-
-
Save Integralist/d84d65c909eeafe4dfca to your computer and use it in GitHub Desktop.
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); | |
}); |
I see what you're up to @Integralist :)
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! :)
@danscotton you've been trying out some FP stuff recently I believe. What do you make of this gist?
The purpose of the script is to poll an endpoint (I'm using RoboHydra to dynamically create endpoints) and for every fail or 304 "not modified" status, increase the timeout before attempting to poll the endpoint again. Otherwise, when you do get a healthy 200 status, reset the timeout back down to a regular interval again.
It seems doing Functional Programming for web development is harder than it appears :-/ especially when doing things like XHR and DOM manipulation.
In this script I've tried to keep to the principles of:
seconds(5)
rather than an ugly direct value of5000
; also I would have preferred to have not referenced the variabledelay
directly within thepoll
function but instead passed the value as a function, but that caused more complications and hoops to jump through - I might take another look at it though - any suggestions? also, I could've passed a function intoincrementDelay
to mutate thedelay
variable but that seemed more overhead for not a lot of real benefit; maybe I'm not drinking enough of the FP kool-aid? lastly, I'm passingendpoint
function as an argument topoll
so I don't have a direct reference toendpoint
but it feels kind of pointless in this current code sample)dispatch
executes each fn in the stack until a truthy value is returned)delay
variable is only mutated in this single file and isn't a global value - although it would be better if I could limit the mutation even further within this file - again, any suggestions?)