Ell*_*rro 5 javascript jwt reactjs redux redux-saga
我的 React 应用程序中的刷新令牌流有一些问题。我使用 axios 拦截器来处理 statusCode === 401 的响应,刷新我的令牌并在此之后重复所有请求。
Axios 拦截器
export const customAxios = axios.create({
headers: {
'Access-Control-Allow-Origin': '*',
'Accept': 'application/json',
"Content-Type": "application/json",
}
});
customAxios.interceptors.response.use(
function(response) {
return response
},
function(error) {
const errorResponse = error.response;
if (isTokenExpiredError(errorResponse)) {
return resetTokenAndReattemptRequest(error);
}
return Promise.reject(error);
}
)
function isTokenExpiredError(errorResponse) {
if (errorResponse.status === 401) {
return true
}
}
let isAlreadyFetchingAccessToken = false;
let subscribers = [];
async function resetTokenAndReattemptRequest(error) {
const {dispatch, getState} = store;
try {
const { response: errorResponse } = error;
const resetToken = getState().login.refreshToken;
if (!resetToken) {
return Promise.reject(error);
}
const retryOriginalRequest = new Promise(resolve => {
addSubscriber(tokens => {
errorResponse.config.headers.Authorization = 'Bearer ' + tokens.accessToken;
resolve(axios(errorResponse.config));
});
});
if (!isAlreadyFetchingAccessToken) {
isAlreadyFetchingAccessToken = true;
const response = await axios.get(`${API}/auth/refreshtoken`, configHeaders(resetToken))
if (!response.data) {
return Promise.reject(error);
}
const newTokens = response.data;
dispatch(refreshTokenSuccess(newTokens))
isAlreadyFetchingAccessToken = false;
onAccessTokenFetched(newTokens);
}
return retryOriginalRequest;
} catch (err) {
return Promise.reject(err);
}
}
function onAccessTokenFetched(tokens) {
subscribers.forEach(callback => callback(tokens));
subscribers = [];
}
function addSubscriber(callback) {
subscribers.push(callback);
}
Run Code Online (Sandbox Code Playgroud)
它工作正常!但是,当用户打开新的浏览器选项卡时,我遇到了刷新功能问题。在我的应用程序中,我有“在线”数据表,其中一些delay
用于重复请求。
Redux-Saga actionChannel 用于发出一些延迟的请求
export function * vehiclesWatcher () {
let getVehiclesTask;
const requestChan = yield actionChannel(GET_VEHICLES_REQUEST);
while (true) {
yield take(requestChan);
getVehiclesTask = yield fork(vehiclesFlow);
yield take([CLEAR_VEHICLES_REQUEST]);
yield cancel(getVehiclesTask);
}
}
Run Code Online (Sandbox Code Playgroud)
车流
function * vehiclesFlow () {
try {
while (true) {
const accessToken = yield select(getToken);
const searchBy = yield select(result);
const id = yield select(getId);
const vehicles = yield call(getAllVehicles, accessToken, id, searchBy);
yield put ({type: GET_VEHICLES_SUCCESS, payload: vehicles});
yield delay(5000);
}
} catch (error) {
} finally {
if (yield cancelled()) {
yield put({type: CLEAR_VEHICLES_SUCCESS});
}
}
}
Run Code Online (Sandbox Code Playgroud)
获取所有车辆
async function getAllVehicles (token, id, searchBy) {
try {
const res = await customAxios.post(`${API}/vehicle/getsorted?take=${15}`,
JSON.stringify({...searchBy, id }), configHeaders(token));
return res.data;
} catch (error) {
throw error;
}
}
Run Code Online (Sandbox Code Playgroud)
如果用户单击表格的一行,则会在新选项卡中打开一个新组件,并且会发出新的服务器请求。
Redux-Saga 操作通道,用于在新的浏览器选项卡中发出一个请求
export function * vehicleWatcher () {
const requestChan = yield actionChannel(GET_VEHICLE_REQUEST);
while (true) {
const { id } = yield take(requestChan);
yield fork(vehicleFlow, id);
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的父窗口。
如果我在服务器响应为 401的同时单击表行,我将在新选项卡中收到响应 401,并且我的 refreshtoken 请求将失败
知道如何解决这个问题吗?当 REFRESH_TOKEN_REQUEST/REFRESH_TOKEN_SUCCESS 操作正在进行时,如何暂停所有传奇?
归档时间: |
|
查看次数: |
1392 次 |
最近记录: |