React-请求取消页面更改

时间:2018-10-02 11:59:24

标签: javascript reactjs axios

我正在使用axios来获取数据/将数据发布到服务器,而我目前的方法如下:

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

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

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) }),
  },
};

在此,我根据redux动作类型创建一个cancelToken并将其存储在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...
}

如您所见,这种方法没有什么大问题,但是如果我在一页上进行大量请求,则必须在componentWillUnmount中手动将其全部取消。

我的问题:

  1. 如果用户在我的应用程序中更改页面,是否可以自动取消正在进行的请求?
  2. 如果是,这样做是正确的方法还是取消请求的简便方法?

1 个答案:

答案 0 :(得分:1)

因此,我要做的是创建一个使用RequestCancelation包的名为history的类。它可以根据传递的操作类型或基于history.location.pathname取消请求。

RequestCancelation.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;

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

也可以作为gist使用。