记录,处理请求优化,取消上一次未发送请求。

371 阅读3分钟

1.问题来源

在又一次的开发中,我没有活干,比较轻松。然后问负责带我的人我现在需要干啥(其实没活干可以自己学习,但没目标的学,属实不知道学啥)。负责带我的那个人比较忙,然后就把最近想解决的一个优化问题但是因为太忙没有时间处理的问题就来告诉了我,我正好闲的没事干,就来找一下。

2.问题需求

说.在发送请求中,如果有多个请求,其中两个请求的接口一个返回的数据特别大(大概几秒),一个返回的数据几乎是瞬间完成,如果点击第一个按钮之后又点击了第二个按钮,同时开始渲染,那渲染理论上应该要渲染第二个请求的数据,但是因为第一个数据请求返回过慢,导致最后渲染了第一个请求的数据。问我该怎么办。(那个业务用的是axios请求)

3.解决问题

第一个脑海中直接闪过了abort,但仅限于知道,所以就去查了查他的用法,但是没查出一个所以然,也不太适合应用于这里,然后我就在这里开始找,但不会搜问题导致也没有搜索到,然后就在加了几个前端微信群里面找大佬问,大佬告诉了一下我axios中有一个cancelTocke可以取消发送请求,并且给了我一个例子,我拿到之后直接粘贴到了例子代码中,肯定也就不行,之后开始翻看Axios官方文档,找到了关于cancelTocke的用法,是这样的(直接照搬的官方文档):

const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 处理错误
}
});

axios.post('/user/12345', {
name: 'new name'
}, {
cancelToken: source.token
})\
\
// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');

之后按照source的用法,模仿着写了两个个请求,试了试,但是两个请求直接发不出去,直接就是被中断的,人傻了。又去看文档,发现这样子发送请求不行,然后还有另一种用法:

const CancelToken = axios.CancelToken;

let cancel;

axios.get('/user/12345', {
  cancelToken: new CancelToken(function executor(c) {
    // executor 函数接收一个 cancel 函数作为参数
    cancel = c;
  })
});

// cancel the request
cancel();

根据这一种写法我又模仿着写了两个请求(这里是我自己写的,其中用到了ts,any请忽略,哈哈哈毕竟ts也是刚接触,在学习中):

import styles from './index.less';
import { useEffect,useState } from 'react';
import { Button } from 'antd';
import axios from 'axios'
const CancelToken = axios.CancelToken
let cancel:any
export default function IndexPage() {
const [cash,useCash] = useState<any>()
 const onc=()=>{
    cancel?.();
    axios.get('/api/users',{
        cancelToken: new CancelToken(function executor(c) {
            cancel = c;
          }),
        params: {
            time: 3
          },
    })
    .then(function (response) {
    useCash(response.data);
 })
    .catch(function (error) {
     console.log(error);
})
 }

 const onc2=()=>{
    cancel?.();
    axios.get('/api/users',{
        cancelToken: new CancelToken(function executor(c) {
            cancel = c;
          }),
        params: {
            time: 5
          },
    })
    .then(function (response) {
    useCash(response.data);
 })
    .catch(function (error) {
     console.log(error);
})
}
  return (
    <div>
      <h1 className={styles.title}>Page index</h1>
      <Button onClick={onc}>3秒返回数据</Button>
      <Button onClick={onc2}>5秒返回数据</Button>
      <h2>{cash}</h2>
    </div>
  );
}

其中大概是怎么运行的,我应该也清楚了,应该是先定义了个全局的cancel变量,然后在每次发送请求之中cancel变为了它来记录一下上一次发送的请求,如果上一次请求已完成(也就是说calcel里面的东西没了)那么就不必理会,如果在发送下一个请求的时候上一个请求未完成(这样就还会显示在cancel中),那么就会覆盖掉上一个请求,让上一个请求终止并且换成这一次发送的请求。最后,就是把这个方法封装成一个工具。之后这个任务也算圆满的完成了,又学到一点东西,来这里记录一下(虽说我说的简单,但是解决的时候真的难,足足费了我好长时间)。如果有哪里我说的不对的,欢迎各位大佬前来指正,我会修改的。