Javascript 将参数从一个Axios请求传递到另一个Axios请求
背景 我正在将内置的React Native应用程序连接到REST API。我通过Axios处理请求,并使用Redux存储查询结果。我有一个用于api连接的index.js文件,其中包含了一些函数,这些函数充当需要越来越深级别授权的请求的处理程序。我有一个简单的函数,返回一个访问令牌,这是由以下代码触发的,当前位于应用程序的“欢迎页面” 理想情况下,在浏览几个屏幕后,用户将进入主页并触发以下代码:Javascript 将参数从一个Axios请求传递到另一个Axios请求,javascript,react-native,rest,redux,axios,Javascript,React Native,Rest,Redux,Axios,背景 我正在将内置的React Native应用程序连接到REST API。我通过Axios处理请求,并使用Redux存储查询结果。我有一个用于api连接的index.js文件,其中包含了一些函数,这些函数充当需要越来越深级别授权的请求的处理程序。我有一个简单的函数,返回一个访问令牌,这是由以下代码触发的,当前位于应用程序的“欢迎页面” 理想情况下,在浏览几个屏幕后,用户将进入主页并触发以下代码: useEffect(() => { dispatch(retrieveData())
useEffect(() => {
dispatch(retrieveData());
}, [dispatch]);
到目前为止,一切顺利。以下是调度触发的功能:
export const getToken = () =>
apiInstance
.request({
url: ENDPOINTS.TOKEN,
data: qs.stringify({
grant_type: 'some_credentials',
c_id: 'some_id',
c_secret: 'some_secret',
}),
headers: {
'content-type': 'some_content_type',
},
method: 'POST',
})
.then(response => {
return response.data;
})
.catch(error => {
return Promise.reject(error.message);
});
export const getData = () =>
apiInstance
.request({
url: ENDPOINTS.DATA,
method: 'POST',
data: qs.stringify({
timestamp: Date.now(),
c_id: 'some_id',
token: **this is the token we get from the previous function**,
}),
headers: {
'content-type': 'some_content_type',
},
})
.then(response => {
return response.data;
})
.catch(error => {
return Promise.reject(error.message);
});
问题
正如我前面提到的,这是一个Redux/Axios解决方案。这意味着状态是全局存储的,但有一个执行顺序。您应该注意到,这两个函数存储在同一个文件中,除非像我之前展示的两个分派调用那样明确说明,否则不会调用它们
问题是,如果我从家中记录令牌(在使用dispatch调用它之后),我可以清楚地看到它,但是如果我尝试从存储请求函数的文件中记录所述令牌,我会得到一个空数组。我尝试用以下所有方法填充令牌字段:
import keyMirror from 'keymirror';
import {createAction} from 'redux-actions';
import {getToken} from '../../api';
export const tokenActionTypes = keyMirror({
RETRIEVE_TOKEN_REQUEST: null,
RETRIEVE_TOKEN_SUCCESS: null,
RETRIEVE_TOKEN_FAILURE: null,
});
const tokenActionCreators = {
request: createAction(tokenActionTypes.RETRIEVE_TOKEN_REQUEST),
success: createAction(tokenActionTypes.RETRIEVE_TOKEN_SUCCESS),
failure: createAction(tokenActionTypes.RETRIEVE_TOKEN_FAILURE),
};
export const retrieveToken = () => dispatch => {
dispatch(tokenActionCreators.request());
getToken()
.then(token => dispatch(tokenActionCreators.success(token)))
.catch(error => dispatch(tokenActionCreators.failure(error)));
};
import {tokenActionTypes} from '../actions/token';
export const initialState = {
loadingToken: false,
token: [],
error: null,
};
const actionsMap = {
[tokenActionTypes.RETRIEVE_TOKEN_REQUEST]: state => ({
...state,
loadingToken: true,
}),
[tokenActionTypes.RETRIEVE_TOKEN_SUCCESS]: (state, action) => ({
...state,
loadingToken: false,
token: action.payload,
}),
[tokenActionTypes.RETRIEVE_TOKEN_FAILURE]: (state, action) => ({
...state,
loadingToken: false,
error: action.payload,
}),
};
export default (state = initialState, action) => {
const actionHandler = actionsMap[action.type];
if (!actionHandler) {
return state;
}
return actionHandler(state, action);
};
减速器代码
import keyMirror from 'keymirror';
import {createAction} from 'redux-actions';
import {getToken} from '../../api';
export const tokenActionTypes = keyMirror({
RETRIEVE_TOKEN_REQUEST: null,
RETRIEVE_TOKEN_SUCCESS: null,
RETRIEVE_TOKEN_FAILURE: null,
});
const tokenActionCreators = {
request: createAction(tokenActionTypes.RETRIEVE_TOKEN_REQUEST),
success: createAction(tokenActionTypes.RETRIEVE_TOKEN_SUCCESS),
failure: createAction(tokenActionTypes.RETRIEVE_TOKEN_FAILURE),
};
export const retrieveToken = () => dispatch => {
dispatch(tokenActionCreators.request());
getToken()
.then(token => dispatch(tokenActionCreators.success(token)))
.catch(error => dispatch(tokenActionCreators.failure(error)));
};
import {tokenActionTypes} from '../actions/token';
export const initialState = {
loadingToken: false,
token: [],
error: null,
};
const actionsMap = {
[tokenActionTypes.RETRIEVE_TOKEN_REQUEST]: state => ({
...state,
loadingToken: true,
}),
[tokenActionTypes.RETRIEVE_TOKEN_SUCCESS]: (state, action) => ({
...state,
loadingToken: false,
token: action.payload,
}),
[tokenActionTypes.RETRIEVE_TOKEN_FAILURE]: (state, action) => ({
...state,
loadingToken: false,
error: action.payload,
}),
};
export default (state = initialState, action) => {
const actionHandler = actionsMap[action.type];
if (!actionHandler) {
return state;
}
return actionHandler(state, action);
};
您可以将一个thunk组合到另一个thunk中,如将get token组合到get data中:
export const retrieveToken = () => (dispatch, getState) => {
//you could use getState() to see if you need to fetch the token
// const tokenResult = selectToken(getState());
// if(token && !token expired) { return Promise.resolve() }
dispatch(tokenActionCreators.request());
//return a promise so you can wait for it
return getToken()
.then(token => dispatch(tokenActionCreators.success(token)))
.catch(error => dispatch(tokenActionCreators.failure(error)));
};
//in retrieve data you can wait for the token
export const retrieveData = () => dispatch => {
dispatch(retrieveToken()).then(
()=>{
//here return getting the data
}
)
};
该代码中的一个可能错误是,一个渲染周期将发送多个thunk,这些thunk将多次获取令牌。您可以通过retrieveToken操作解决此问题,该操作具有在解析时失效的缓存:
const invalidateOnResolveCache = (cache = new Map()) => {
return {
get: (key) => cache.get(key),
set: (key, value) => cache.set(key, value),
resolved: (x) => cache.delete(key),
};
};
或者,您可以为需要令牌的所有Thunk编写一个wrap函数:
//group retrieveToken in such a way that if it's called multiple times
// during a render cycle the token request will only be made once
//https://gist.github.com/amsterdamharu/2dde4a6f531251f3769206ee44458af7
export const needsToken =
(fn) =>
(...args) =>
(dispatch, getState) =>
dispatch(retrieveToken(...args)).then(() =>
//you could use getState to get the token and pass it to
// fn together with the other args
// for example: fn(...args.concat(selectToken(getState())))
fn(...args)
);
export const autoTokenRetrieveData = needsToken(retrieveData);
//use needsToken for any other thunk actions that need a token
例如:
const{Provider,useDispatch,useSelector}=ReactRedux;
const{createStore,applyMiddleware,compose}=Redux;
const{createSelector}=重新选择;
//分组代码以对操作进行分组
//群承诺返回函数
常量创建组=
(缓存)=>
(fn,getKey=(…x)=>JSON.stringify(x))=>
(…args)=>{
const key=getKey(args);
让result=cache.get(key);
如果(结果){
返回结果;
}
//无缓存
结果=Promise.resolve(fn.apply(null,args))。然后(
(r) =>{
cache.resolved(key);//告诉缓存承诺完成
返回r;
},
(e) =>{
cache.resolve(key);//告诉缓存承诺完成
退回承诺。拒绝(e);
}
);
cache.set(键、结果);
返回结果;
};
//thunk动作创建者不是(…args)=>结果,而是
//(…args)=>(调度,getState)=>结果
//下面是我们如何将thunk动作分组的
const createGroupedThunkAction=(thunkAction,缓存)=>{
const group=createGroup(缓存)(
(args、dispatch、getState)=>
thunkAction.apply(null,args)(dispatch,getState)
);
返回(…参数)=>
(调度,getState)=>{
返回组(args、dispatch、getState);
};
};
常量createInvalidateOnResolveCache=(
缓存=新映射()
) => {
返回{
get:(key)=>cache.get(key),
set:(键,值)=>cache.set(键,值),
已解析:(键)=>cache.delete(键),
};
};
//获取令牌的函数
const uniqueToken=(
(令牌)=>()=>
代币++
)(1);
const fetchToken=()=>Promise.resolve(uniqueToken());
常量初始状态={
数据1:[],
数据2:[],
令牌:null,
};
//动作类型
const DATA_SUCCESS='DATA_SUCCESS';
const GOT_TOKEN='GOT_TOKEN';
//动作创造者
const dataSuccess=(数据,键)=>({
类型:DATA_SUCCESS,
有效负载:{key,data},
});
const gotToken=(令牌)=>({
类型:GOT_TOKEN,
有效载荷:令牌,
});
const reducer=(状态,{type,payload})=>{
如果(类型===数据\u成功){
const{data,key}=有效载荷;
返回{
……国家,
[键]:数据,
};
}
如果(类型===GOT\u令牌){
返回{
……国家,
代币:{
值:有效载荷,
已创建:Date.now(),
},
};
}
返回状态;
};
//thunk获取数据
const getData1=(令牌)=>(分派)=>
Promise.resolve()然后(()=>
派遣(
数据成功(
`已获取带有标记的数据1:${token}`,
“数据1”
)
)
);
const getData2=(令牌)=>(分派)=>
Promise.resolve()然后(()=>
派遣(
数据成功(
`已获取带有标记的数据2:${token}`,
“数据2”
)
)
);
//thunk正在获取令牌:
常量getToken=()=>(调度)=>
fetchToken()。然后((token)=>dispatch(gotToken(token));
//分组thunk获取令牌
常量getTokenGrouped=createGroupedThunkAction(
格托克,
createInvalidateOnResolveCache()
);
尼德斯托克常数=
(fn)=>
(…args)=>
(调度,getState)=>{
让承诺;
//仅当令牌的时间超过1秒时才获取该令牌
const tokenResult=selectToken(getState());
如果(
标记结果&&
Date.now()-新日期(tokenResult.created).getTime()<
1000
) {
promise=promise.resolve();
}否则{
允诺