Last active
November 21, 2016 06:09
-
-
Save muendelezaji/ce3878d1ce9617a4e42a25d7aa755ef3 to your computer and use it in GitHub Desktop.
Exponential backoff strategy for a generic asynchronous function call
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Retry with Backoff</title> | |
</head> | |
<body> | |
<pre id="result"></pre> | |
</body> | |
</html> |
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
// JSFiddle - https://jsfiddle.net/mdzj/dwwx0889 | |
// Inspired by https://jsfiddle.net/pajtai/pLka0ow9 | |
// HTML: <pre id="result"></pre> | |
// main | |
retryWithBackoff(sometimesFailsAsync, 10, 1000, 30000, function (error, result) { | |
console.log('final result is', error ? error : result); | |
}); | |
var percentFail = 0.8; | |
// Replace default | |
console.log = consoleLog; | |
function consoleLog() { | |
var args = [].slice.apply(arguments); | |
args.unshift((new Date()).toISOString()); // prepend date | |
document.querySelector('#result').innerHTML += '\n' + args.join(' - '); | |
} | |
function sometimesFailsAsync (callback) { | |
var asyncDelay = Math.floor(Math.random() * 5000); | |
console.log('async delay', asyncDelay); | |
setTimeout(function () { | |
var value = Math.random(); | |
if (value >= percentFail) { | |
error = null; | |
result = 'success = ' + value; | |
} else { | |
error = new Error('failed = ' + value); | |
result = null; | |
} | |
return callback(error, result); | |
}, asyncDelay); | |
} | |
function retryWithBackoff (func, attempts, minWait, maxWait, callback) { | |
var wait = +minWait || 100; // first wait will be 100ms if not specified | |
var retry = function (fn, cb) { | |
console.log('retries left', attempts, 'next try in', wait); | |
setTimeout(function () { return fn(cb); }, wait); // retry after wait time elapsed | |
wait = wait < maxWait / 2 ? wait * 2 : maxWait; // increase wait time for next attempt | |
} | |
var repeater = function (error, result) { | |
if (!error) { | |
return callback(null, result); | |
} else { | |
if (attempts-- > 0) { | |
return retry(func, repeater); | |
} else { | |
return callback(error); // 0 attempts left, give up | |
} | |
} | |
} | |
console.log('starting...'); | |
return func(repeater); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
JSFiddle — https://jsfiddle.net/mdzj/dwwx0889