前端3种方案解决重复请求后端数据

目录

         解决方案一:简单粗暴法

1、用JavaScript控制表单只能提交一次

2、提交以后将提交按钮设置为不可用(体验可能不太好)

3、提交以后将页面关闭(可能用户体验不好)

4、采用页面重定向

解决方案二:axios拦截器

解决方案三  cancelToken


        遇到重复请求的问题,即一次请求还没有执行完毕,用户又点击了一次,这样重复请求会造成后台数据异常。又比如在查询数据的时候点击了一次查询,还在处理数据的时候,用户又点击了一次查询。第一次查询执行完毕页面已经有数据展示出来了,用户可能正在看呢,此时第二次查询也处理完返回到前台把页面刷新了,就会造成很不好的体验。

解决方案一:简单粗暴法

1、用JavaScript控制表单只能提交一次

<form action="${pageContext.request.contextPath}/servlet/DoFormServlet" οnsubmit="return dosubmit()" method="post">
    用户名:<input type="text" name="username">
    <input type="submit" value="提交" id="submit">
</form>

<head>
    <title>Form表单</title>
    <script type="text/javascript">
        var isCommitted = false;//表单是否已经提交标识,默认为false
        function dosubmit(){
            if(isCommitted==false){
                isCommitted = true;//提交表单后,将表单是否已经提交标识设置为true
                return true;//返回true让表单正常提交
            } else {
                return false;//返回false那么表单将不提交
            }
        }
    </script>
</head>

2、提交以后将提交按钮设置为不可用(体验可能不太好)

function dosubmit(){
    //获取表单提交按钮
    var btnSubmit = document.getElementById("submit");
    //将表单提交按钮设置为不可用,这样就可以避免用户再次点击提交按钮
    btnSubmit.disabled= "disabled";
    //返回true让表单可以正常提交
    return true;
}

3、提交以后将页面关闭(可能用户体验不好)

4、采用页面重定向

        在用户点击提交按钮之后,转向一个新的页面,提示用户提交成功。

解决方案二:axios拦截器

        axios的拦截器分为请求拦截器和响应拦截器,顾名思义就是指在请求服务器之前和服务器数据返回到前台的时候可以对数据或者头信息进行操作处理。这里主要是使用请求拦截器,在请求拦截器中取消之前的请求。

请求拦截器

axios.interceptors.request.use(function(config){
        // console.log(config);
        //例如在请求中拼接头信息
        config.headers.token = 'lalal';
        
        return config;
    },function(ret){
        console.log(ret);
    })

响应拦截器

axios.interceptors.response.use(function(config){
        // console.log(config);
        //例如在请求中拼接头信息
        config.headers.token = 'lalal';
        
        return config;
    },function(ret){
        console.log(ret);
    })

解决方案三  cancelToken

这是axios提供的一个api,用法如下

let CancelToken = axios.CancelToken;
var f;
//这里的参数c其实是一个函数
config.cancelToken = new CancelToken(function executor(c){
    f = c;
});
//如果需要取消这个请求,调用函数即可
f();

        逻辑很简单,这里的每个请求都对应着有自己的取消函数,在每次执行之前都将当前请求的取消函数赋给f。然后在发起请求之前判断f存不存在,如果存在则就是前一个请求的取消函数,执行前一个请求的取消函数就可以了。当然这里有不严谨的地方,例如在请求结束后可以重新将f置为空,不然上一个请求已经处理完了也会执行取消。

	let pending = []; //声明一个数组用于存储每个请求的取消函数和axios标识
let cancelToken = axios.CancelToken;
let removePending = (config) => {
    console.log('pending',pending);
    for(let p in pending){
        if(pending[p].u === config.url.split('?')[0] + '&' + config.method) { 
        //当当前请求在数组中存在时执行函数体
            pending[p].f(); //执行取消操作
            pending.splice(p, 1); //数组移除当前请求
        }
    }
}
//请求拦截
.interceptors.request.use(function(config) { 
    /*.....*/
  removePending(config); //在一个axios发送前执行一下取消操作
  config.cancelToken = new cancelToken((c)=>{
        // pending存放每一次请求的标识,一般是url + 参数名 + 请求方法,当然你可以自己定义
    pending.push({ u: config.url.split('?')[0] +'&' + config.method, f: c});//config.data为请求参数
  });
   /*.....*/

})

//请求完毕之后将这个请求从pending数组中移除
    axios.interceptors.response.use(function(data) { 
        var identity = data.config.url +'&'+data.config.method;
        let index = pending.findIndex(item => item.u == identity);
        pending.splice(index,1);
        return data;
    })

猜你喜欢

转载自blog.csdn.net/m0_64346035/article/details/125177485