JSFiddle - React, Tailwind, and code Playground
HTML
<script>var Attempt=function(){function c(d,e){return this instanceof c?(this.promise=a(),this.promiseGenerator=d,this.decisionGenerator=e||b,this.currentAttemptNumber=0,this.error=null,this._attempt(),this.promise):new c(d,e)}var a=function(){return{then:function(){throw new Error("Attempt.configure() before use Attempt")}}},b=function(){return!1};return c.configure=function(b){a=b},c.prototype={_attempt:function(){var a=this,b=a.promise;a.promiseGenerator(a.error,a.currentAttemptNumber).then(function(a){(b.fulfill||b.resolve).call(b,a)},function(b){a.error=b,a.currentAttemptNumber++;var c=a.createDecide(),d=!1;try{d=a.decisionGenerator(a.error,a.currentAttemptNumber,c)}catch(e){}"undefined"!=typeof d&&c(d)})},_decide:function(a){var b=this;return 1/0===a||"undefined"==typeof a||a===!1||null===a?(this.promise.reject(this.error),void 0):"function"==typeof a.then?(this._followPromise(a),void 0):(this.promise.notify([this.error,this.currentAttemptNumber]),setTimeout(function(){b._attempt()},a),void 0)},_followPromise:function(a){var b=this;a.then(function(a){b._decide(a)},function(){b._decide()})},createDecide:function(){var a=this,b=!1;return function(c){return b?void 0:(b=!0,a._decide.call(a,c))}}},c}();</script>
<pre></pre>
JavaScript
Attempt.configure(function () {
return $.Deferred();
});
new Attempt(toGetJson, decideOnReject)
.pipe(resolve, reject, progress);
function toGetJson() {
return $.getJSON('/json');
}
function decideOnReject(err, attemptNo) {
if (err && err.status > 500) {
return false;
}
// repeat request in N * 500 ms
if (attemptNo <= 5) {
return attemptNo * 500;
}
// To many attempts - network or server totally down,
// we should ask user what to do
return askUserWhatTodo(attemptNo);
}
function askUserWhatTodo(attemptNo) {
var dfd = $.Deferred();
// setImmediate
setTimeout(function () {
var result = window.confirm('We had tried to send request ' + attemptNo + ' times. Continue?');
var nextAttemptIn = attemptNo * 500;
if (result) {
dfd.resolve(nextAttemptIn);
} else {
dfd.reject();
}
}, 0);
return dfd.promise();
}
function log(str) {
$('<div>' + str + '</div>').appendTo('pre');
}
function resolve(data) {
log(data);
}
function reject() {
log('I tried several times... and fail :( ');
}
function progress(args) {
log('Failed to load, retrying... ' + args[1]);
}