2017-10-15 2 views
0

다음 작업을 실행하기 전에 새로 고침 토큰으로 이동하여 액세스 토큰이 만료되면 다른 작업을 실행할 수있는 미들웨어가 있습니다.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-무용담 혜택을 누릴 수

+0

미들웨어의 isLoading 값을 확인하는 곳이 표시되지 않습니다. – Freez

+0

다른 것을 시도해 보았습니다. 다시 보셨습니까? ? – ccoeder

+0

예! Im 호기심 – Freez

답변

0

는 당신의 행동을 모니터링하고 일부 특정 조치가 충족 될 때 반응 할 수 단지 배경 주자이다. 당신은 모든 작업에 대해 듣고 모든 반응 또는

https://redux-saga.js.org/docs/api/#takelatestpattern-saga-args

동안의 REDUX-썽크 이동 작업을 생성하고 몇 가지 내가 기다리는 또 다른 방법입니다 주석에 언급 한 바와 같이 당신은 단지 최근에 반응 할 수 있습니다/O를 수행 한 다음 I/O가 완료되면 더 많은 작업을 생성합니다. 이것은 동기화 된 코드 패턴과 같으며 redux-sagas는 멀티 스레드와 비슷합니다. 메인 스레드에서 앱을 실행하고 백그라운드 스레드에 서사 모니터와 반응이 있습니다.