Problem Overview:
I have a GreaseMonkey/TamperMonkey script in FireFox that sends several GM_xmlhttpRequest
(essentially similar to a xml http request, however this wrapper allows ease in cross-origin requests) to URL's to retrieve simple JSON data. Some of the JSON data retrieved is super simple, like so,
{id:123459876, code:"frog"}
[{value:"water", contents:0}]
This leads me to my outline of what code I've got down for my programming task so far, and, eventually shapes what I'll ask in the end as my question.
Problem Outline: Since the workflow I'm essentially doing is as follows; (based off this SO question/answer)
- Send a
'GET'
request withGM_xmlhttpRequest
inside aPromise
object
function makeRequest(reqMethod, navURL) {
return new Promise(function (resolve, reject) {
GM_xmlhttpRequest({
method: reqMethod,
url: navURL,
onload: function () {
if (this.status >= 200 && this.status < 300) {
resolve(this.response);
} else {
reject({
status: this.status,
statusText: this.statusText
});
}
},
onprogress: function(event) {
console.log(`Loaded ${event.loaded} of ${event.total}`);
},
onerror: function(data) {
reject({
status: this.status,
statusText: this.statusText
});
}
});
});
}
- Upon returning a successful status within the
GM_xmlhttpRequest
- the promise returns the JSON as the resolve response.
function makeRequestWrapper(requestMethod, navToURL, successFunction) {
makeRequest(requestMethod, navToURL)
.then(
function (datums) {
successFunction(datums);
}
)
.catch(
function (err) {
console.error('there was an error!', err.statusText);
}
);
}
- Have the initial promise, upon success resolve, run a post processing function to update the current window page with the retrieved JSON data
// one of the 3 example handler methods for dealing with the success + JSON
function successHandler1(jsonDataResponse) {
let response = JSON.parse(jsonDataResponse);
let id = response[0].id;
let updateLink = document.getElementById("unique_link_id").parentNode.parentNode;
updateLink .innerHTML += ` ID: ${id} `;
}
Up until this point, my code works as I've intended, the Promise on success returns the JSON data and I update my current window page with that retrieved data.
However, my issue is that some users of the script that pulls this JSON data will have the Promise fail (some more frequently than others) - thus my next step of triage I'm attempting is retrying Promise's a certain number of times, and, with a delay. This way, I figure retrying a failed Promise, let's say 3 times, with 3 second delays, should give ample attempts and time to increase the success rate for the Promise.
My thoughts
Since I am a relative newbie to JS (still learning it and hopefully becomes a language I can use in life), I've read things like Promises and Observables? and rethink if I'm on the right path with this problem. I think I need an in-depth example, specific to my use case, and, with thorough step-by-step explanation, in order to learn more about not only Promises, but also this use-case scenario.
So far, I have attempted to integrate my working code with these SO answers about promises with retry, like:
- Promise Retry Design Patterns
- Generic promise retry logic
- Retry on Javascript.Promise.reject a limited number of times or until success
- Recursive retry in Promise
- How to retry an xhr request which returns a promise recursively for atleast n times on status 0
- Promises: Repeat operation until it succeeds?
- general solution to retry a promise in javascript
As well as reading blog posts, like;
- Retry Pattern in Node.js using Promise
- JavaScript: Promises and Why Async/Await Wins the Battle
- Retry Sync/Async(Promises) functions of Javascript
I've also looked at countless doc's, like;
- https://developer.mozilla.org/en-US/docs/Web/API/
- https://wiki.greasespot.net/
- https://javascript.info/
- https://devdocs.io/javascript/
And finally, some random (not as well structured) links;
Question
How do I go about converting my existing code to an aforementioned example, or, creating a new API-like method to handle my existing code (work around what I have)?