How To Retry An Xhr Request Which Returns A Promise Recursively For Atleast N Times On Status 0
Solution 1:
Here's how I'd approach it (see ***
comments):
var makeRequest = function(method, urlToBeCalled, payload) {
var deferred = $q.defer();
var retries = 4; // *** Counterrun(); // *** Call the workerreturn deferred.promise;
// *** Move the actual work to its own functionfunctionrun() {
var xhr = newXMLHttpRequest();
xhr.open(method, encodeURI(urlToBeCalled), true);
setHttpRequestHeaders(xhr);
xhr.onload = function() {
if (xhr.status === 200 && xhr.readyState === 4 && xhr.getResponseHeader('content-type') !== 'text/html') {
try {
response = JSON.parse(xhr.response);
deferred.resolve(response);
} catch (e) {
deferred.reject(e);
}
} elseif (xhr.status === 0) {
// retryif (retries--) { // *** Recurse if we still have retries run();
} else {
// *** Out of retries
deferred.reject(e);
}
} else {
// *** See note below, probably remove thistry {
response = JSON.parse(xhr.response);
deferred.reject(response);
} catch (e) {
deferred.reject(xhr.response);
}
}
};
xhr.onerror = function() {
deferred.reject(xhr.response);
};
xhr.send(payload);
}
};
Side note: The content of your initial if
body and the final else
appear to be identical. I think I'd recast the entire onload
:
xhr.onload = function() {
if (xhr.readyState === 4) {
// It's done, what happened?if (xhr.status === 200) {
if (xhr.getResponseHeader('content-type') !== 'text/html') {
try {
response = JSON.parse(xhr.response);
deferred.resolve(response);
} catch (e) {
deferred.reject(e);
}
} else {
// Something went wrong?
deferred.reject(e);
}
} elseif (xhr.status === 0) {
// retryif (retries--) { // *** Recurse if we still have retries run();
} else {
// *** Out of retries
deferred.reject(e);
}
}
}
};
Re your comment:
This does resolve my current problem but is there a way to resolve all the promises which are added to call stack if any one of those is resolved?
Yes: To do that with Angular's $q
(I assume that's what you're using), you can just pass the promise you get back from the recursive call into resolve
on your deferred object: Since it's a promise, the deferred will wait for it to be settled and resolve or reject based on what that promise does. If you do this at every level in the chain, the resolutions work their way up the chain:
angular.module("mainModule", []).controller(
"mainController",
function($scope, $q, $http) {
test(true).then(function() {
test(false);
});
functiontest(flag) {
log(flag ? "Testing resolved" : "Testing rejected");
returnrecursive(3, flag)
.then(function(arg) {
log("Resolved with", arg);
})
.catch(function(arg) {
log("Rejected with", arg);
});
}
functionrecursive(count, flag) {
log("recursive(" + count + ", " + flag + ") called");
var d = $q.defer();
setTimeout(function() {
if (count <= 0) {
// Done, settleif (flag) {
log("Done, resolving with " + count);
d.resolve(count);
} else {
log("Done, rejecting with " + count);
d.reject(count);
}
} else {
// Not done, resolve with promise from recursive calllog("Not done yet, recursing with " + (count - 1));
d.resolve(recursive(count - 1, flag));
}
}, 0);
return d.promise;
}
}
);
functionlog() {
var p = document.createElement('pre');
p.appendChild(
document.createTextNode(
Array.prototype.join.call(arguments, " ")
)
);
document.body.appendChild(p);
}
pre {
margin: 0;
padding: 0;
}
<divng-app="mainModule"><divng-controller="mainController"></div></div><scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
You can do the same thing with JavaScript's own promises:
test(true).then(function() {
test(false);
});
functiontest(flag) {
log(flag ? "Testing resolved" : "Testing rejected");
returnrecursive(3, flag)
.then(function(arg) {
log("Resolved with", arg);
})
.catch(function(arg) {
log("Rejected with", arg);
});
}
functionrecursive(count, flag) {
log("recursive(" + count + ", " + flag + ") called");
returnnewPromise(function(resolve, reject) {
setTimeout(function() {
if (count <= 0) {
// Done, resolve with valueif (flag) {
log("Done, resolving with " + count);
resolve(count);
} else {
log("Done, rejecting with " + count);
reject(count);
}
} else {
// Not done, resolve with promise// from recursive calllog("Not done yet, recursing with " + (count - 1));
resolve(recursive(count - 1, flag));
}
}, 0);
});
}
functionlog() {
var p = document.createElement('pre');
p.appendChild(
document.createTextNode(
Array.prototype.join.call(arguments, " ")
)
);
document.body.appendChild(p);
}
pre {
margin: 0;
padding: 0;
}
Post a Comment for "How To Retry An Xhr Request Which Returns A Promise Recursively For Atleast N Times On Status 0"