React - 请求取消页面更改

Anc*_*nek 6 javascript reactjs axios

我正在axios用于获取/发布数据到我的服务器,我目前的方法如下所示:

1. 使用带有 的 redux 动作发出请求redux-thunk,动作如下所示:

export const getRecords = () => (dispatch, getState, { api }) => {
  const type = GET_RECORDS_LOAD;
  return dispatch({
    type,
    promise: api.Records.get({ type }),
  });
};
Run Code Online (Sandbox Code Playgroud)

2.api.Record.get看起来像这样:

import _ from 'lodash';
import axios from 'axios';

const APIInstance = axios.create({
  baseURL: process.env.API_URL,
});

const getCancelToken = id => new axios.CancelToken((c) => {
  const cancel = c;
  const cancelationTokens = _.get(window, 'cancelationTokens', {});
  cancelationTokens[id] = cancel;
  _.set(window, 'cancelationTokens', cancelationTokens);
});

const api = {
  Records: {
    get: ({ type }) => APIInstance.get('/my-records', { cancelToken: getCancelToken(type) }),
  },
};
Run Code Online (Sandbox Code Playgroud)

在这里,我cancelToken根据 redux 操作类型创建了一个,并将其存储在一个window.cancelationTokens对象中,因此可以从应用程序的任何位置取消它们。

3. 取消 componentWillUnmount

import * as Types from './path/to/action/types';

const cancelToken = (type) => {
  const cancel = _.get(window, `cancelationTokens.${type}`);
  if (!cancel) return;
  cancel();
}

componentWillUnmount() {
  cancelToken(Types.GET_RECORDS_LOAD);
  // If more request I have to cancel them manually...
}
Run Code Online (Sandbox Code Playgroud)

如您所见,这种方法没有大问题,但是如果我在一个页面上执行大量请求,我必须在componentWillUnmount.

我的问题:

  1. 如果用户更改了我的应用程序中的页面,有没有办法自动取消正在进行的请求?
  2. 如果是 - 这样做是正确的方法,还是有更简单的方法来取消请求?

Anc*_*nek 4

所以,我所做的是创建一个名为RequestCancelation使用historypackage.json 的类。它可以根据传递的操作类型或基于history.location.pathname.

请求取消.js

import _ from 'lodash';
import axios from 'axios';
import createHistory from 'history/createBrowserHistory';

// In my case the history is imported from another file, as I pass
// it to the `Router` from `react-router-dom`. For the purpose of this
// example I created the history here.
const history = createHistory();

class RequestCancelation {
  static constants = {
    cancelationTokens: 'CANCELATION_TOKENS',
  }

  getTokens() {
    return _.get(window, RequestCancelation.constants.cancelationTokens, {});
  }

  setTokens(tokens) {
    return _.set(window, RequestCancelation.constants.cancelationTokens, tokens);
  }

  deleteTokens(key) {
    if (!key) return undefined;
    delete window[RequestCancelation.constants.cancelationTokens][key];
    return this.getTokens();
  }

  getLocationKey() {
    return _.get(history, 'location.pathname');
  }

  getCancelToken(type) {
    return new axios.CancelToken((c) => {
      const cancel = c;
      if (typeof window === 'undefined') return;
      const tokens = this.getTokens();
      if (type) {
        tokens[type] = cancel;
      } else {
        const key = this.getLocationKey();
        if (!key) return;
        if (!tokens[key]) tokens[key] = [];
        tokens[key].push(cancel);
      }
      this.setTokens(tokens);
    });
  }

  cancelRequest(type) {
    if (!type) {
      return console.warn('#cancelRequest - please specify \'type\'');
    }
    if (typeof window === 'undefined') return undefined;
    const tokens = this.getTokens();
    const cancel = tokens[type];
    if (!cancel) return undefined;
    cancel();
    return this.deleteTokens(type);
  }

  cancelRequests() {
    if (typeof window === 'undefined') return undefined;
    const tokens = this.getTokens();
    const key = this.getLocationKey();
    if (!key) return undefined;
    const cancels = tokens[key];
    if (!cancels) return undefined;
    cancels.forEach(cancel => cancel());
    return this.deleteTokens(key);
  }

  clearTokens() {
    if (typeof window === 'undefined') return undefined;
    window[RequestCancelation.constants.cancelationTokens] = {};
    return this.getTokens();
  }
}

const cancelation = new RequestCancelation();

export default cancelation;
Run Code Online (Sandbox Code Playgroud)

希望这对某人有帮助,也许有人可以改进它:)

也可作为要点