« Back to Index
Polling example with back pressure handling
View original Gist on GitHub
polling.js
define(['module/bootstrap', 'module/dispatch', 'config'], function(news, dispatch, config) {
var URL = config.dynamic.broker;
var cb;
function seconds(secs) {
return secs * 1000;
}
function minutes(mins) {
return mins * seconds(60);
}
function incrementDelay() {
if (delay < THRESHOLD) {
delay *= 2;
}
return delay; // we return a value for the sake of our `dispatch` method called by `statusChecks`
}
var statusChecks = dispatch(
function(status) { return status === 304 ? incrementDelay() : null; },
function(status) { return status === 200 ? delay = seconds(5) : null; },
function(status) { return status === 420 ? true : null; },
function(status) { return status === 'timeout' ? true : null; }
);
function isSafeToCallback(status, rest) {
return status ? executeCallback(rest[0]) : null;
}
function trackTimeout() {
failCount++;
return disablePolling(failCount > FAIL_THRESHOLD);
}
function tooManyRequests(timeout, resultFromStatusCheck) {
return timeout ? trackTimeout() : resultFromStatusCheck;
}
function disablePolling(status) {
return status ? true : false;
}
function delayPolling(disabled) {
if (!disabled) {
incrementDelay();
poll(endpoint(URL));
}
}
function executeCallback(data) {
cb(data);
poll(endpoint(URL));
}
function success(data, status, xhr) {
isSafeToCallback(
statusChecks(xhr.status), data
);
}
// This alias helps make a call to statusChecks inside failure fn clearer
// Otherwise it would look like we're calling the same function twice
var checkForTimeout = statusChecks;
function failure(xhr, status, error) {
delayPolling(
disablePolling(
tooManyRequests(
checkForTimeout(status), statusChecks(xhr.status)
)
)
);
}
function postDataAssetTemplate(data) {
return {
"type": "asset",
"payload": {
"component_id": data.id,
"options": data.opts
}
};
}
function generateJsonData() {
var obj = config.dynamic.components;
var data = { requests: [] };
for (var prop in obj) {
data.requests.push(
postDataAssetTemplate(obj[prop])
);
}
return JSON.stringify(data);
}
function endpoint(url) {
return (function(url) {
return function() {
news.$.ajax(url, {
processData : false,
type : 'post',
contentType : 'application/json',
data : generateJsonData(),
timeout : seconds(5)
}).then(success, failure);
};
}(url));
}
function poll(endpoint) {
return window.setTimeout(endpoint, delay);
}
// Constants
var THRESHOLD = seconds(20);
var FAIL_THRESHOLD = 5;
// Mutables
var delay = seconds(5);
var failCount = 0;
return function(callback) {
cb = callback;
poll(endpoint(URL));
};
});
// Fuzzying the delay was a bit confusing so left it for now