Javascript 取消axios时出现问题。然后使用拦截器和取消令牌执行逻辑
我为我的react应用程序设置了axios响应拦截器。它可以很好地捕捉大多数错误,但我遇到的一个问题是,如果响应是401,即用户未经授权,拦截器会将用户发送回登录页面。现在这可以工作了,但是内部的逻辑仍然在运行。这会导致一个类型错误,如逻辑中所示。然后,我正在使用响应数据设置一个状态。下面是我当前尝试实现的axios取消令牌,但该令牌不起作用。请参阅下面的代码。我错过了什么?在不必向每个axios请求添加If/Else逻辑以检查“数据”是否存在或响应是否为401200…,实现这一点的最佳方法是什么 AxiosInterceptor.js UserPage.js 我得到的错误:Javascript 取消axios时出现问题。然后使用拦截器和取消令牌执行逻辑,javascript,reactjs,redux,axios,redux-persist,Javascript,Reactjs,Redux,Axios,Redux Persist,我为我的react应用程序设置了axios响应拦截器。它可以很好地捕捉大多数错误,但我遇到的一个问题是,如果响应是401,即用户未经授权,拦截器会将用户发送回登录页面。现在这可以工作了,但是内部的逻辑仍然在运行。这会导致一个类型错误,如逻辑中所示。然后,我正在使用响应数据设置一个状态。下面是我当前尝试实现的axios取消令牌,但该令牌不起作用。请参阅下面的代码。我错过了什么?在不必向每个axios请求添加If/Else逻辑以检查“数据”是否存在或响应是否为401200…,实现这一点的最佳方法是什
Unhandled Rejection (TypeError): Cannot read property 'data' of undefined
进度更新:
我在后端添加了一些逻辑,如果登录成功
export default withRouter({
useSetupInterceptors: (history) => {
let user = useSelector(state => state.user)
axios.interceptors.request.use(config => {
const { onLogo } = useLogout(history);
console.log("Current Status = ", user.exp, Date.now() > user.exp)
if (Date.now() > user.exp) {
Swal.fire({
title: '401 - Auth Failed',
text: '',
icon: 'warning',
showCancelButton: false,
confirmButtonText: 'Return',
}).then((result) => {
onLogo();
})
return {
...config,
cancelToken: new CancelToken((cancel) => cancel('Cancel')) // Add cancel token to config to cancel request if redux-store expire value is exceeded
};
} else {
return config;
}
}, error => { console.log(error)});
axios.interceptors.response.use(response => {
return response;
}, error => {
try {
if (axios.isCancel(error)) { // check if canceled
return new Promise(() => {}); // return new promise to stop axios from proceeding to the .then
}
if (error.response.status === 401) {
history.push("/login");
Swal.fire({
title: '401 - Auth Failed',
text: '',
icon: 'warning',
showCancelButton: false,
confirmButtonText: 'Close',
})
throw new axios.Cancel('Operation canceled');
}
return Promise.reject(error);
} catch (error) {
console.log(error)
}
});
},
});
function useLogo(history) {
const dispatch = useDispatch()
return {
onLogo() {
dispatch(allActs.userActs.logOut())
history.push("/login");
},
}
}
我在react redux中找到了钩子“useSelector”的问题。这似乎是在缓存数据已经返回正确数据之后,如何返回缓存数据。我当时使用的是7.2版,但我也在7.1版上确认了这一点。我没有测试过任何其他版本。我通过在下面的
getExpire()
函数中从redux persist Storage(localStorage)提取数据来解决这个问题。这不是最优雅的解决方案,但我的应用程序现在可以正常工作了
export default withRouter({
useSetupInterceptors: (history) => {
const { onLogout } = useLogout(history);
const CancelToken = axios.CancelToken;
const { onExp } = useExp();
axios.interceptors.request.use((config) => {
const testexp = onExp();
if (testexp) {
Swal.fire({
title: '401 - Authorization Failed',
text: '',
icon: 'warning',
showCancelButton: false,
confirmButtonText: 'Return',
}).then((result) => {
onLogout();
})
return {
...config,
cancelToken: new CancelToken((cancel) => cancel('Cancel repeated request'))
};
} else {
return config;
}
}, error => { console.log(error) });
axios.interceptors.response.use(response => {
return response;
}, error => {
try {
if (axios.isCancel(error)) {
return new Promise(() => { });
}
return Promise.reject(error);
} catch (error) {
console.log(error)
}
});
},
});
function getExpire () {
var localStore = localStorage.getItem("persist:root")
if (localStore) {
let store = JSON.parse(localStore)
return JSON.parse(store.exp)
}
return 0
}
function useExp() {
// const currentExp = useSelector(state => state.exp)
return {
onExp() {
if (Date.now() > getExpire().exp) {
return true
} else { return false }
},
}
}
function useLogout(history) {
const dispatch = useDispatch()
return {
onLogout() {
dispatch(allActions.expAction.setLogout())
history.push("/login");
},
}
}
检查什么是响应
然后(res=>{console.log(res)})
感谢您的快速响应!我知道我可以检查响应并使用If/Else逻辑来决定在401事件中应该做什么,但我想看看是否有一种方法可以在拦截器/全局级别这样做,而不必将其添加到每个页面上的每个axios请求中。不幸的是,我查看了那篇文章,似乎我的问题已经从那里转移了。你知道吗检查axios中间件?您还可以创建自己的中间件来全局处理错误。
// from redux-logger
action SET_EXP @ 20:05:42.721
redux-logger.js:1 prev state {user: {…}, _persist: {…}}
redux-logger.js:1 action {type: "SET_EXP", payload: 1585267561036}
USEREXP 1585267561036 // this is the new EXP time set in redux, received from back end on login
AxiosInterceptors.js:17 Current Status = 1585267561036 false // first two axios calls on main page validate and indicate not expired
AxiosInterceptors.js:17 Current Status = 1585267561036 false
AxiosInterceptors.js:17 Current Status = 1585267495132 true // this is the value of the previos exp value that was set
AxiosInterceptors.js:17 Current Status = 1585267495132 true
AxiosInterceptors.js:17 Current Status = 1585267352424 true // this is the value that was set two login times ago
AxiosInterceptors.js:17 Current Status = 1585267352424 true
export default withRouter({
useSetupInterceptors: (history) => {
let user = useSelector(state => state.user)
axios.interceptors.request.use(config => {
const { onLogo } = useLogout(history);
console.log("Current Status = ", user.exp, Date.now() > user.exp)
if (Date.now() > user.exp) {
Swal.fire({
title: '401 - Auth Failed',
text: '',
icon: 'warning',
showCancelButton: false,
confirmButtonText: 'Return',
}).then((result) => {
onLogo();
})
return {
...config,
cancelToken: new CancelToken((cancel) => cancel('Cancel')) // Add cancel token to config to cancel request if redux-store expire value is exceeded
};
} else {
return config;
}
}, error => { console.log(error)});
axios.interceptors.response.use(response => {
return response;
}, error => {
try {
if (axios.isCancel(error)) { // check if canceled
return new Promise(() => {}); // return new promise to stop axios from proceeding to the .then
}
if (error.response.status === 401) {
history.push("/login");
Swal.fire({
title: '401 - Auth Failed',
text: '',
icon: 'warning',
showCancelButton: false,
confirmButtonText: 'Close',
})
throw new axios.Cancel('Operation canceled');
}
return Promise.reject(error);
} catch (error) {
console.log(error)
}
});
},
});
function useLogo(history) {
const dispatch = useDispatch()
return {
onLogo() {
dispatch(allActs.userActs.logOut())
history.push("/login");
},
}
}
export default withRouter({
useSetupInterceptors: (history) => {
const { onLogout } = useLogout(history);
const CancelToken = axios.CancelToken;
const { onExp } = useExp();
axios.interceptors.request.use((config) => {
const testexp = onExp();
if (testexp) {
Swal.fire({
title: '401 - Authorization Failed',
text: '',
icon: 'warning',
showCancelButton: false,
confirmButtonText: 'Return',
}).then((result) => {
onLogout();
})
return {
...config,
cancelToken: new CancelToken((cancel) => cancel('Cancel repeated request'))
};
} else {
return config;
}
}, error => { console.log(error) });
axios.interceptors.response.use(response => {
return response;
}, error => {
try {
if (axios.isCancel(error)) {
return new Promise(() => { });
}
return Promise.reject(error);
} catch (error) {
console.log(error)
}
});
},
});
function getExpire () {
var localStore = localStorage.getItem("persist:root")
if (localStore) {
let store = JSON.parse(localStore)
return JSON.parse(store.exp)
}
return 0
}
function useExp() {
// const currentExp = useSelector(state => state.exp)
return {
onExp() {
if (Date.now() > getExpire().exp) {
return true
} else { return false }
},
}
}
function useLogout(history) {
const dispatch = useDispatch()
return {
onLogout() {
dispatch(allActions.expAction.setLogout())
history.push("/login");
},
}
}