axios本身并不能处理中止情况,和智能终止,以及节流缓存等功能,我们在使用@redux-requests就可以发挥它的特性,来看下吧
对于这个正常的redux-requests
配置的代码,只需要在加一个code码的判断和处理,对于store代码应该是这样的。
import axios from 'axios';
const axiosInit = axios.create({
baseURL: API_BASE,
});
axiosInit.interceptors.response.use(response => {
// token invalid
if ([-1, -2].includes(response.data?.errorCode)) {
store.dispatch(abortRequests());
store.getState().login.outLogin();
}
return response;
});
const { requestsReducer, requestsMiddleware } = handleRequests({
driver: {
default: createDriver({
processResponse: response => ({ data: response }),
}),
axiosSmartchain: createAxiosDriver(axiosInit),
},
});
const rootReducer = combineReducers({
requests: requestsReducer,
login: loginReducer,
});
export const store = configureStore({
reducer: rootReducer,
middleware: [
...requestsMiddleware,
],
});
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType;
从上面代码可以看出,对于token无效的情况, 只有两个处理,一个是中止请求,另外一个是退出登录的处理。
store.dispatch(abortRequests());
store.getState().login.outLogin();
退出登录后界面改变成需要登录的样子,这个每个页面可能都不太一样或者一样,但是都有一个特点就是不再依赖需要登录才有的数据,所以数据可以去掉,对于数据的取消,上面是全部取消,如果比较高级一点的,有正对性的取消的方式是dispatch(abortRequests(actions.map(e => e.toString())))
这个abortRequests
属性是个好东西,它不是取消请求,而是如果可以取消请求,那么取消请求,如果请求完成,但是还没响应那么拒绝响应,和abort不是同一个东西,axios自己本身是没有这个功能的,axios只能取消请求,但是无法做到取消响应。
对于outLogin,这个操作我是放store,因为退出操作依赖hooks,没办法直接调用。
loginReducer.ts
import { createSlice } from '@reduxjs/toolkit';
const loginSlice = createSlice({
name: 'login',
initialState: {
outLogin: () => {
// await init function
},
},
reducers: {
setOutLogion: (state, action) => {
state.outLogin = action.payload;
},
},
});
export const { setOutLogion } = loginSlice.actions;
const loginReducer = loginSlice.reducer;
export default loginReducer;
公共组件的退出操作的地方设置退出函数
const outLogin = useCallback(() => {
localStorage.clear();
deactivate();
handleDisconnect && handleDisconnect();
}, [deactivate, handleDisconnect]);
useEffect(() => {
dispatch(setOutLogion(outLogin));
}, [dispatch, outLogin]);
之所以要用中止的方式,是这样具体实现的时候就不需要考虑是否正常状态,如下面。getData这个都可以直接用id函数。
export const fetchItem = createSmartAction<
RequestAction
>('fetchItem', (params: { contract: string; id: number }, meta) => ({
request: {
url: '/api/v2/main/auth/getoneitembyid',
method: 'post',
data: { ct: params.contract, id: params.id },
},
meta: {
getData: _.id,
auth: true,
driver: 'axiosSmartchain',
asMutation: false,
...meta,
},
}));
--完--