#javascript #api #recursion #closures
Вопрос:
Мне нужна помощь в организации моего кода, чтобы я мог рекурсивно повторить неудачные запросы api. Вот пример функции, которая вызывает api (у меня есть несколько подобных функций, которые выполняют различные вызовы api с полезной нагрузкой и принимают функцию обратного вызова, в рамках обещания функция ApiCall издевается над ней):
function boilerPlateApiCall() {
return new Promise(((resolve, reject) => {
// make an api call
apiCall('GET',(err, res) => {
if (err) { return reject(err); }
resolve(res);
});
}))
.then(res => res.data)
.catch(handleErrors(boilerPlateApiCall, []));
}
Вот моя handleErrors
функция:
function handleErrors(recursiveFunc, parameters) {
const handleError = function handleError(err) {
console.log('Error in request: ', recursiveFunc.name);
console.log('Error is ', err);
console.log('handleErrors');
if (err.code === 401) {
console.log('authorizing and trying again');
}
if (err.code === 404) {
console.log('404');
return Promise.resolve();
}
if (err.code === 403 || err.code === 503) {
console.log('too many requests');
setTimeout(() => {
recursiveFunc(...parameters);
}, 1000);
}
return Promise.reject(err);
}
};
return handleError;
}
handleErrors
Функция используется в a .catch
для всех методов api. Основная причина handleErrors
заключается в регистрации ошибок и возможности получить имя функции, в которой возникает ошибка. Однако, исходя из структуры, в операторе if, который проверяет наличие кодов состояния 403 и 503, это будет выполняться бесконечно, если будут возвращены одни и те же коды.
Из-за структуры этого кода (в частности, функции catch в boilerPlateApiCall
) функция handleErrors вызывается всякий раз , когда возникает ошибка. Я не могу понять, как обернуть setTimeout
рекурсивный вызов в какой-то тип закрытия, чтобы ограничить количество повторных попыток/попыток.
В идеале я хочу что-то подобное, но поскольку boilerPlateApiCall
вызывает ошибки обработки в .catch, закрытие сбрасывается при каждой попытке:
function handleErrors(recursiveFunc, parameters) {
let numberOfRetries = 5;
const handleError = function handleError(err) {
console.log('Error in request: ', recursiveFunc.name);
console.log('Error is ', err);
console.log('handleErrors');
if (err.code === 401) {
console.log('authorizing and trying again');
}
if (err.code === 404) {
console.log('404');
return Promise.resolve();
}
if (err.code === 403 || err.code === 503) {
console.log('too many requests');
if(numberOfRetries > 0){
numberOfRetries--
setTimeout(() => {
recursiveFunc(...parameters);
}, 1000);
}
}
return Promise.reject(err);
}
};
return handleError;
}
Единственный способ, который я могу придумать для этого, — это, возможно, передавать каждой функции вызова api ( boilerPlateApiCall
) аргумент «повторная попытка», а затем передавать аргумент повторной попытки handleErrors
.
Комментарии:
1. Если вы контролируете функции api, то , возможно
boilerPlateApiCall (3 , ...moreArgs)
, вызоветеhandleError (3, boilerplateApiCall, moreArgs)
, который при сбое проверит, является лиnumberOfRetries
(этот первый параметр) положительным. Если это так, то он вызоветrecursiveFunc (numberOfRetries - 1, ...moreArgs)
, если это не так, вы переходите к окончательной ошибке. Все это зависит от того, сможете ли вы изменить APIboilerPlateApiCall
. Если ты не можешь этого сделать, тогда мне придется больше думать.2. Спасибо, Скотт. У меня есть доступ к функциям api. Я думал об этом маршруте, но предпочел бы не идти этим путем, так как для получения дополнительного аргумента потребуется обновить множество функций. Я действительно в тупике, и, возможно, мне придется пойти по предложенному вами маршруту.