Skip to content

Instantly share code, notes, and snippets.

@so298
Last active November 17, 2023 08:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save so298/374d27b395980d2847eff0fa7bc7d754 to your computer and use it in GitHub Desktop.
Save so298/374d27b395980d2847eff0fa7bc7d754 to your computer and use it in GitHub Desktop.
API呼び出しに失敗したりタイムアウトしたときに複数回APIをコールするためのラッパー関数
/**
*
* @param targetFunc fetch function
* @param opt retry options
* @returns
*/
export const retryFetch = <T>(
targetFunc: () => Promise<T>,
opt?: {
retryCount?: number;
retryTimeout?: number; // seconds
}
): Promise<T> => {
return new Promise((resolve, reject) => {
const retryCount = opt?.retryCount || 3;
const retryTimeout = opt?.retryTimeout || 10;
let count = 0;
// Change intervalId's type to `number | undefined` if you use in browser
let intervalId: NodeJS.Timeout | undefined = undefined;
const clearAndResolve = (res: T) => {
if (intervalId) clearInterval(intervalId);
resolve(res);
};
const clearAndReject = (err: Error) => {
if (intervalId) clearInterval(intervalId);
reject(err);
};
const intervalFunc = () => {
count++;
if (count > retryCount) {
clearAndReject(new Error('Retry count exceeded'));
}
// Repeat unit
const repeatFunc = () => {
targetFunc()
.then((res) => {
clearAndResolve(res);
})
.catch(() => {
// If error catched, clear interval and start another interval.
if (intervalId) clearInterval(intervalId);
intervalFunc();
});
};
// Because the first interval start after retryTimeout seconds,
// we need to call repeatFunc() once in outside of setInterval().
repeatFunc();
// interval start
intervalId = setInterval(() => {
count++;
if (count > retryCount) {
clearAndReject(new Error('Retry count exceeded'));
}
repeatFunc();
}, retryTimeout * 1000);
};
// Start the first interval
intervalFunc();
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment