Ajax-запросы завершаются неудачно, а затем завершаются успешно при повторной попытке с предварительным фильтромJquery

Программирование на jquery
Ответить
Anonymous
 Ajax-запросы завершаются неудачно, а затем завершаются успешно при повторной попытке с предварительным фильтром

Сообщение Anonymous »

У меня есть функция на основе jquery, которая предварительно фильтрует все запросы ajax, чтобы она могла перехватывать запросы 401 и обновлять авторизацию API.
Раньше я использовал функцию, которая просто проверяет наличие 401, обновляет аутентификацию и повторно отправляет первоначальный запрос. Проблема заключалась в том, что многие обновления запускались одновременно, что обычно приводило к сбою.
Я заменил его чем-то, что проверяет, происходит ли обновление, и, если да, добавляет запросы в очередь. Теперь проблема, с которой я столкнулся, заключается в том, что исходные запросы не выполняют обещание и выдают ошибку, прежде чем их повторно запускают и добиваются успеха. Это проблема для некоторых функций, которые не работают после последующего повторного запуска.
Я хочу, чтобы повторный выпуск ajax был прозрачным, чтобы мне не приходилось обрабатывать ошибки при каждом отдельном вызове ajax. В более простом коде этой проблемы не было. К сожалению, у меня недостаточно знаний, чтобы разобраться в логике обещаний.
Код префильтра выглядит следующим образом
var isRefreshing = false;
var refreshQueue = [];

function addQueue(cb) {
refreshQueue.push(cb);
}

function onRefreshed(token) {
refreshQueue.forEach(cb => cb(token));
refreshQueue = [];
}

$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
// Skip refresh endpoint itself
if (options.url.includes('/refresh') || options.url.includes('refresh')) {
return;
}

// Add token to every request
var token = localStorage.getItem('access_token');
if (token) {
jqXHR.setRequestHeader('Authorization', 'Bearer ' + token);
}

// Hook into the fail handler
jqXHR.fail(function(jqXHR, textStatus, errorThrown) {
if (jqXHR.status === 401 && !originalOptions._retry) {
var retryOriginalRequest = new $.Deferred();

if (isRefreshing) {
// Wait for the ongoing refresh
addQueue(function(newToken) {
// Retry with new token
originalOptions.headers = originalOptions.headers || {};
console.log(originalOptions);
// originalOptions.headers['Authorization'] = 'Bearer ' + newToken;
originalOptions._retry = true;

$.ajax(originalOptions)
.then(retryOriginalRequest.resolve, retryOriginalRequest.reject);
});
} else {
// Start refresh
isRefreshing = true;

$.ajax({
url: 'api/refresh',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({
access_token: localStorage.getItem('access_token')
// or refresh_token: localStorage.getItem('refresh_token')
})
})
.done(function(res) {
var newToken = res.access_token || res.token;
localStorage.setItem('access_token', newToken);

// Update global headers for future requests
$.ajaxSetup({
headers: { 'Authorization': 'Bearer ' + newToken }
});

onRefreshed(newToken);

// Retry original
// originalOptions.headers['Authorization'] = 'Bearer ' + newToken;
originalOptions._retry = true;
$.ajax(originalOptions).then(retryOriginalRequest.resolve, retryOriginalRequest.reject);
})
.fail(function() {
console.log("Refresh fail");
onRefreshed(null); // notify all waiting requests failed
// Optional: logout
// localStorage.clear();
// location.href = '/login';
retryOriginalRequest.reject(jqXHR, textStatus, errorThrown);
})
.always(function() {
isRefreshing = false;
});
}

jqXHR.then(null, function() {
return retryOriginalRequest;
});
}
});
});


Подробнее здесь: https://stackoverflow.com/questions/798 ... -prefilter
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Jquery»