J'ai un middleware qui peut aller au jeton d'actualisation avant l'exécution de l'action suivante, puis exécuter l'autre action à l'expiration du jeton d'accès. Mais si je fais plus d'une demande à la fois et que le jeton d'accès est terminé, j'essaie d'obtenir autant de jetons d'actualisation que je le demande. Je vérifie la propriété isLoading dans l'état pour empêcher ceci. Mais après la requête, la valeur de isLoading est vraie dans le réducteur, elle semble être fausse dans le middleware, donc elle demande encore et encore.redux refresh middleware de jeton
J'envoie refreshTokenPromise dans l'action fetching_refresh_token, mais je n'obtiens jamais state.refreshTokenPromise, il est toujours indéfini.
J'ai vraiment un problème avec l'état.
Donc, voici ma question, comment puis-je accéder à la valeur de changement d'état dans le middleware?
Refresh middleware jeton: (cette version touche le point final à plusieurs reprises)
import { AsyncStorage } from 'react-native';
import { MIN_TOKEN_LIFESPAN } from 'react-native-dotenv';
import moment from 'moment';
import Api from '../lib/api';
import {
FETCHING_REFRESH_TOKEN,
FETCHING_REFRESH_TOKEN_SUCCESS,
FETCHING_REFRESH_TOKEN_FAILURE } from '../actions/constants';
export default function tokenMiddleware({ dispatch, getState }) {
return next => async (action) => {
if (typeof action === 'function') {
const state = getState();
if (state) {
const expiresIn = await AsyncStorage.getItem('EXPIRES_IN');
if (expiresIn && isExpired(JSON.parse(expiresIn))) {
if (!state.refreshToken.isLoading) {
return refreshToken(dispatch).then(() => next(action));
}
return state.refreshTokenPromise.then(() => next(action));
}
}
}
return next(action);
};
}
async function refreshToken(dispatch) {
const clientId = await AsyncStorage.getItem('CLIENT_ID');
const clientSecret = await AsyncStorage.getItem('CLIENT_SECRET');
const refreshToken1 = await AsyncStorage.getItem('REFRESH_TOKEN');
const userObject = {
grant_type: 'refresh_token',
client_id: JSON.parse(clientId),
client_secret: JSON.parse(clientSecret),
refresh_token: refreshToken1,
};
const userParams = Object.keys(userObject).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(userObject[key])).join('&');
const refreshTokenPromise = Api.post('/token', userParams).then(async (res) => {
await AsyncStorage.setItem('ACCESS_TOKEN', res.access_token);
await AsyncStorage.setItem('REFRESH_TOKEN', res.refresh_token);
await AsyncStorage.setItem('EXPIRES_IN', JSON.stringify(res['.expires']));
dispatch({
type: FETCHING_REFRESH_TOKEN_SUCCESS,
data: res,
});
return res ? Promise.resolve(res) : Promise.reject({
message: 'could not refresh token',
});
}).catch((err) => {
dispatch({
type: FETCHING_REFRESH_TOKEN_FAILURE,
});
throw err;
});
dispatch({
type: FETCHING_REFRESH_TOKEN,
refreshTokenPromise,
});
return refreshTokenPromise;
}
function isExpired(expiresIn) {
return moment(expiresIn).diff(moment(), 'seconds') < MIN_TOKEN_LIFESPAN;
}
Refresh réducteur jeton:
import {
FETCHING_REFRESH_TOKEN,
FETCHING_REFRESH_TOKEN_SUCCESS,
FETCHING_REFRESH_TOKEN_FAILURE } from '../actions/constants';
const initialState = {
token: [],
isLoading: false,
error: false,
};
export default function refreshTokenReducer(state = initialState, action) {
switch (action.type) {
case FETCHING_REFRESH_TOKEN:
return {
...state,
token: [],
isLoading: true,
};
case FETCHING_REFRESH_TOKEN_SUCCESS:
return {
...state,
isLoading: false,
token: action.data,
};
case FETCHING_REFRESH_TOKEN_FAILURE:
return {
...state,
isLoading: false,
error: true,
};
default:
return state;
}
}
En attendant, quand je l'envoie à la getState à la fonction refreshToken, J'arrive à la valeur de changement d'état dans le refreshToken. Mais dans cette version, le jeton d'actualisation va à d'autres actions sans être actualisé.
Singe version patchée: (cette version ne fait que 1 demande)
import { AsyncStorage } from 'react-native';
import { MIN_TOKEN_LIFESPAN } from 'react-native-dotenv';
import moment from 'moment';
import Api from '../lib/api';
import {
FETCHING_REFRESH_TOKEN,
FETCHING_REFRESH_TOKEN_SUCCESS,
FETCHING_REFRESH_TOKEN_FAILURE } from '../actions/constants';
export default function tokenMiddleware({ dispatch, getState }) {
return next => async (action) => {
if (typeof action === 'function') {
const state = getState();
if (state) {
const expiresIn = await AsyncStorage.getItem('EXPIRES_IN');
if (expiresIn && isExpired(JSON.parse(expiresIn))) {
if (!state.refreshTokenPromise) {
return refreshToken(dispatch, getState).then(() => next(action));
}
return state.refreshTokenPromise.then(() => next(action));
}
}
}
return next(action);
};
}
async function refreshToken(dispatch, getState) {
const clientId = await AsyncStorage.getItem('CLIENT_ID');
const clientSecret = await AsyncStorage.getItem('CLIENT_SECRET');
const refreshToken1 = await AsyncStorage.getItem('REFRESH_TOKEN');
const userObject = {
grant_type: 'refresh_token',
client_id: JSON.parse(clientId),
client_secret: JSON.parse(clientSecret),
refresh_token: refreshToken1,
};
if (!getState().refreshToken.isLoading) {
const userParams = Object.keys(userObject).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(userObject[key])).join('&');
const refreshTokenPromise = Api.post('/token', userParams).then(async (res) => {
await AsyncStorage.setItem('ACCESS_TOKEN', res.access_token);
await AsyncStorage.setItem('REFRESH_TOKEN', res.refresh_token);
await AsyncStorage.setItem('EXPIRES_IN', JSON.stringify(res['.expires']));
dispatch({
type: FETCHING_REFRESH_TOKEN_SUCCESS,
data: res,
});
return res ? Promise.resolve(res) : Promise.reject({
message: 'could not refresh token',
});
}).catch((err) => {
dispatch({
type: FETCHING_REFRESH_TOKEN_FAILURE,
});
throw err;
});
dispatch({
type: FETCHING_REFRESH_TOKEN,
refreshTokenPromise,
});
return refreshTokenPromise;
}
}
function isExpired(expiresIn) {
return moment(expiresIn).diff(moment(), 'seconds') < MIN_TOKEN_LIFESPAN;
}
Merci.
Je ne vois pas où vous vérifiez la valeur isLoading dans le middleware .. – Freez
J'ai essayé d'autres choses, réparé, regarderiez-vous à nouveau ? – ccoeder
Bien sûr! Im curieux – Freez