다음 작업을 실행하기 전에 새로 고침 토큰으로 이동하여 액세스 토큰이 만료되면 다른 작업을 실행할 수있는 미들웨어가 있습니다.redux 새로 고침 토큰 미들웨어
하지만 한 번에 두 개 이상의 요청을하고 액세스 토큰이 끝난 경우 요청하는만큼 새로 고침 토큰을 얻으려고합니다. 이 상태를 방지하기 위해 상태에서 isLoading 속성을 확인합니다. 그러나 요청 후, isLoading 값은 감속기에서 true이며, 미들웨어에서 false 인 것처럼 보이므로 여러 번 요청합니다.
fetching_refresh_token 작업에서 refreshTokenPromise를 보내고 있지만 state.refreshTokenPromise를 얻지 못했습니다. 항상 정의되지 않습니다.
나는 상태에 분명 문제가있다.
여기 내 질문이 있습니다. 어떻게 미들웨어의 상태 값 변경에 액세스 할 수 있습니까?
새로 고침 토큰 미들웨어 : (이 버전은 엔드 포인트 안타를 여러 번)
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;
}
새로 고침 토큰 감속기 : 한편
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;
}
}
, 내가 refreshToken 함수에의 getState로 보낼 때, refreshToken에서 상태 값이 변하게됩니다. 그러나이 버전에서 새로 고침 토큰은 새로 고치지 않고 다른 작업으로 이동합니다.
원숭이 패치 버전 :
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;
}
감사합니다 (이 버전은 1 개 요청합니다). 당신이
https://github.com/redux-saga/redux-saga
REDUX-무용담 REDUX-무용담 혜택을 누릴 수
미들웨어의 isLoading 값을 확인하는 곳이 표시되지 않습니다. – Freez
다른 것을 시도해 보았습니다. 다시 보셨습니까? ? – ccoeder
예! Im 호기심 – Freez