思路:
1.首先利用 axios拦截器 自动检测未完成的请求
2.路由跳转前判断,react-router4提供了一个Prompt组件,react Router 4 版本Router组件(我这里是HashRouter)提供了一个属性 getUserConfirmation ,可在该方法上进行处理,这样就能在切页面的时候自动获取到变化,(tab选项卡也可以)
function App() { return ( <Provider store={store}> <HashRouter getUserConfirmation={getConfirmation}> <LocaleProvider> <> <Prompt message="Are you sure you want to leave?"></Prompt> <Main /> </> </LocaleProvider> </HashRouter> </Provider > ); } ReactDOM.render( <App /> , document.getElementById('app') );
const allPendingRequestsRecord = []; const pending = {}; function removeAllPendingRequestsRecord() { allPendingRequestsRecord && allPendingRequestsRecord.forEach((func) => { func('page changes'); // 取消请求 }); allPendingRequestsRecord.splice(0); // 移除所有记录 } const getConfirmation = (message, callback) => { removeAllPendingRequestsRecord(); callback(true); }; const removePending = (key, isRequest = false) => { if (pending[key] && isRequest) { pending[key]('取消重复请求'); } delete pending[key]; }; axios.interceptors.request.use( config => { // 在请求发送前执行一下取消操作,防止连续点击重复发送请求(例如连续点击2次按钮) const reqData = config.url + config.method; removePending(reqData, true); // 设置请求的 cancelToken config.cancelToken = new axios.CancelToken(c => { pending[reqData] = c; allPendingRequestsRecord.push(c); }); return config; }, error => { Promise.reject(error); } ); axios.interceptors.response.use( response => { return response; }, error => { throw new Error('!接口请求错误'); } );
如果项目中业务逻辑需要页面单独处理可以在组件封装中处理,添加cancelToken函数,
import axios from 'axios';
const CancelToken = axios.CancelToken;
const allPendingRequestsRecord = [];
const query = (options = {}) => axios({
method: 'get',
...options,
headers: {
'Authorization': 'bearer ' + (localStorage.getItem('authData') || ''),
...options.headers,
},
cancelToken: new CancelToken((c) => {
allPendingRequestsRecord.push(c);
}),
}).then(data => data.data || {}).catch(res => {
console.log('cancelReq', res);
});
const request = (options) => query(options);
request.removeAllPendingRequestsRecord = () => {
allPendingRequestsRecord && allPendingRequestsRecord.forEach((cancel) => {
cancel && cancel(); // 取消请求
});
allPendingRequestsRecord.splice(0);
};
request.get = (url, options = {}) => query({ url, ...options });
如果单独在saga中使用axios,
如果单独在saga中使用axios,
const CancelToken = axios.CancelToken;
let cancel = null;
function* removeAllPendingRequestsRecord() {
//正在请求的接口中断函数
cancel && cancel();
}
const response = yield call(axios.post, url, payload, {
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})});
在业务逻辑处理中调用removeAllPendingRequestsRecord函数。