The main objective is to Implement a re-try functionality if the screen is frozen. If the API call to save the test fails, then the code will re-try at least 3 times.
I want to add a retry function in a fetch the API but had an output of a bad request in the console. Also, I don't know if I have the correct placement of the action to invoke the srfl_save_response action. Can someone help me? This is the code below:
function fetchWithAutoRetry(fetcher,maxRetryCount){
return new Promise((resolve,reject) => {
let retries=0;
const caller= () => fetcher(
jQuery(document).trigger('srfl_save_response', [ question_id, question_index, question_type, question_response ])
)
.then((data)=> {
resolve(data);
})
.catch((error) => {
if(retries < maxRetryCount){
retries ;
caller();
}else{
reject(error);
}
});
retries=1;
caller();
});
}
const fetchAdminAjax = async () => {
fetch("https://test.tutorials.com/wp-admin/admin-ajax.php", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
question_id,
question_index,
question_type,
question_response,
}),
})
.then((res) => res.json())
.then((data) => console.log(data))
.catch((error) => console.error(error));
// const jsonResponse = await rawResponse.json();
// return jsonResponse;
// console.log(rawResponse);
};
fetchWithAutoRetry(fetchAdminAjax, 3);
I tried using let in fetch but still bad request
CodePudding user response:
You can use a simple, async for
loop.
For example
const asyncAutoRetry = async (asyncFn, limit) => {
for (let i = 0; i < limit; i ) {
try {
return await asyncFn();
} catch (err) {
console.warn("Failed attempt", i 1, err);
}
}
throw new Error(`${limit} max attempts reached`);
};
const asyncAutoRetry = async (asyncFn, limit) => {
for (let i = 0; i < limit; i ) {
try {
return await asyncFn();
} catch (err) {
console.warn("Failed attempt", i 1, err);
}
}
throw new Error(`${limit} max attempts reached`);
};
const fakeFetch = (succeedAfter) => {
let attempt = 0;
return () => new Promise((resolve, reject) => {
if ( attempt > succeedAfter) {
return resolve("Done");
}
reject("Failed fetch");
});
};
asyncAutoRetry(fakeFetch(2), 3).then(console.log).catch(console.error);
You just need to ensure that your requests fail properly
// Handy wrapper to check for unsuccessful responses and return JSON
const fetchWrapper = async (url, init = {}) => {
const res = await fetch(url, init);
if (!res.ok) {
const err = new Error(`${res.status} ${res.statusText}`);
err.text = await res.text();
throw err;
}
return res.json();
};
asyncAutoRetry(
() =>
fetchWrapper("https://staging.tutorialsdojo.com/wp-admin/admin-ajax.php", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
question_id,
question_index,
question_type,
question_response,
}),
}),
3
)
.then(console.log)
.catch(console.error);
CodePudding user response:
Normally I would ensapsulate fetch call in another method, let's say that is retryFetch
, then in that method you can define the fetch call recursively with number of retries, delays etc. Those attributes can be passed via parameters.
retryFetch(url, retries = 5, interval = 1000, options = {})
So this retryFetch
function could be like this, notice if error occurs the same function is being invoked in the specified interval until all retry count is exhausted.
private wait(delay) {
return new Promise((resolve) => setTimeout(resolve, delay));
}
private retryFetch(url, delay = 1000, tries = 3, fetchOptions = {}) {
let that = this;
function one rror(err) {
let triesLeft = tries - 1;
if (!triesLeft) {
console.log(`err after retry ${triesLeft} api - ` err);
throw err;
}
return that.wait(delay).then(() => that.retryFetch(url, delay, triesLeft, fetchOptions)); <--------------------- Note here
}
function handleErrors(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
return fetch(url, fetchOptions).then(handleErrors).catch(onError);
}
Now you can call it.
const body: string = JSON.stringify({
question_id,
question_index,
question_type,
question_response,
}),
let serviceResponse = this.retryFetch("https://staging.tutorialsdojo.com/wp-admin/admin-ajax.php", 1000, 3
, {
headers: {
"Content-Type": "application/json",
},
body: body
}
);
let finalData = (await serviceResponse).json();