我正在使用axios
来获取数据/将数据发布到服务器,而我目前的方法如下:
redux-thunk
的redux操作发出请求,操作如下所示:export const getRecords = () => (dispatch, getState, { api }) => {
const type = GET_RECORDS_LOAD;
return dispatch({
type,
promise: api.Records.get({ type }),
});
};
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
对象中,以便可以在应用程序的任何位置取消它们。
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
中手动将其全部取消。
我的问题:
答案 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使用。