如何在React Native中取消所有挂起的Axios请求



My React Native应用程序使用axios连接到后端。这是在文件myApi.js:中完成的

class client {
axiosClient = axios.create({
baseURL: example.com,
});
async get(url, data, config) {
return this.axiosClient.get(url, data, config);
}
async put(url, data, config) {
return this.axiosClient.put(url, data, config);
}
async post(url, data, config) {
return this.axiosClient.post(url, data, config);
}
}
export default new client();

我有一个组件,它包含一个由日期选择器控制的useEffect。所选日期保存在名为DateContext的上下文中。当所选日期更改时,会触发一个请求以获取该日期的一些数据。当返回数据时,它会显示给用户。

组件是:

const DaySelect = () => {
const {dateState} = useContext(DateContext);
useEffect(() => {
const load = () => {
const url = '/getDataForDate';
const req = {
selectedDate: moment(dateState.currentDate).format(
'YYYY-MM-DD',
),
};
myApi
.post(url, req)
.then((res) => {
// Now put results into state so they will be displayed
})
};
load();
}, [dateState.currentDate]);
return (
<View>
<>
<Text>Please select a date.</Text>
<DateSelector />
<Results />
</>
)}
</View>
);
};
export default DaySelect;

DateSelector只是选择日期的组件;日期的任何更改都会更新dateState.currentDate的值。Results会显示数据。

只要用户单击一个日期,并在单击新日期之前等待结果显示,这种方法就可以正常工作。但是,如果他们点击了几次,那么每次都会触发一个请求,并在每个请求完成时显示结果数据。由于请求没有按照开始的顺序完成,这通常会导致显示错误的数据。

为了避免这种情况,我认为在提出新的请求之前,我需要取消任何现有的请求。我尝试过使用Abort Controller来完成此操作,但它似乎没有任何作用。

我在myApi.js中添加了以下内容:

const controller = new AbortController();
class client {
axiosClient = axios.create({
baseURL: example.com,
});
async get(url, data, config) {
return this.axiosClient.get(url, data, config);
}
async put(url, data, config) {
return this.axiosClient.put(url, data, config);
}
async post(url, data, config) {
return this.axiosClient.post(url, data, config, {signal: controller.signal});
}
async cancel() {
controller.abort();
}
}
export default new client();

然后在我的主要组件中,我进行

myApi.cancel()

在提出新请求之前。

不过,这似乎没有任何作用——请求不会被取消。我在这里做错了什么?

编辑:根据Ibrahim下面的建议,我将api文件更改为:

const cancelTokenSource = axios.CancelToken.source();
class client {
axiosClient = axios.create({
baseURL: example.com,
});
async post(url, data, config) {
const newConfig = {
...config,
cancelToken: cancelTokenSource.token
};
return this.axiosClient.post(url, data, newConfig);
}
async cancel() { // Tried this with and without async
cancelTokenSource.cancel();
}
}
export default new client();

这使得api调用完全失败。

步骤1:生成取消令牌

const cancelTokenSource = axios.CancelToken.source();

步骤2:为每个请求分配取消令牌

axios.get('example.com/api/getDataForDate', {
cancelToken: cancelTokenSource.token
});
// Or if you are using POST request
axios.post('example.com/api/postApi', {data}, {
cancelToken: ancelTokenSource.token,
});

步骤3:使用取消令牌取消请求

cancelTokenSource.cancel();

在myApi中,我使用AbortController来确保当出现新的可取消请求时,任何可取消的请求都会被中止:

let controller = new AbortController();
class client {
axiosClient = axios.create({
baseURL: example.com,
});
async post(url, data, config, stoppable) {
let newConfig = {...config};
// If this call can be cancelled, cancel any existing ones
// and set up a new AbortController
if (stoppable) {
if (controller) {
controller.abort();
}
// Add AbortSignal to the request config
controller = new AbortController();
newConfig = {...newConfig, signal: controller.signal};
}
return this.axiosClient.post(url, data, newConfig);
}
}
export default new client();

然后,在我的组件中,我将"stopper"作为true传递;通话后,我检查通话是否中止。如果没有,我显示结果;否则我将忽略响应:

useEffect(() => {
const load = () => {
const url = '/getDataForDate';
const req = {
selectedDate: moment(dateState.currentDate).format(
'YYYY-MM-DD',
),
};
myApi
.post(url, req, null, true)
.then((res) => {
if (!res.config.signal.aborted) {
// Do something with the results
}
})
.catch((err) => {
// Show an error if the request has failed entirely
});
};
load();
}, [dateState.currentDate]);

最新更新