react router 4 页面跳转前 axios中断未完成的请求

思路:

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,

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函数。