注册

vue阻止重复请求(下)

接:vue阻止重复333请求(上)

(c)代码

步骤1-通过axios请求拦截器取消重复请求

通过axios请求拦截器,在每次请求前把请求信息和请求的取消方法放到一个map对象当中,并且判断map对象当中是否已经存在该请求信息的请求,如果存在取消上传请求

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
   <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.min.js" type="application/javascript"></script>
   <script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/axios/0.26.0/axios.min.js" type="application/javascript"></script>
   <script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/qs/6.10.3/qs.js" type="application/javascript"></script>

</head>
<body>
   <div id="app">
       <button @click="onClick1" ref="btn1">请求1</button>
       <button @click="onClick2" ref="btn2">请求2</button>
   </div>
</body>
<script>
//存储请求信息和取消方法的的map对象    
const pendingRequest = new Map();  
//根据请求的信息(请求方式,url,请求get/post数据),产生map的key
function getRequestKey(config){
   const { methodurlparamsdata } = config;
   return [methodurlQs.stringify(params), Qs.stringify(data)].join("&");
}  
//请求拦截器
axios.interceptors.request.use(
   function (config) {
   //根据请求的信息(请求方式,url,请求get/post数据),产生map的key
   let requestKey = getRequestKey(config)
   //判断请求是否重复
   if(pendingRequest.has(requestKey)){
       //取消上次请求
       let cancel = pendingRequest.get(requestKey)
       cancel()
       //删除请求信息
       pendingRequest.delete(requestKey)
  }
   //把请求信息,添加请求到map当中
   // 生成取消方法
   config.cancelToken = config.cancelToken || new axios.CancelToken(cancel => {
       // 把取消方法添加到map
       if (!pendingRequest.has(requestKey)) {
           pendingRequest.set(requestKeycancel)
      }
  })
   return config;
},
(error=> {
    return Promise.reject(error);
}
);
let sendPost = function(data){
   return axios({
       url'http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test',
       method'post',
       data
  })
}
new Vue({
   el'#app',
   mounted() {
       this.$refs.btn1.click()
       this.$refs.btn2.click()
  },
   methods: {
       // 使用lodash对请求方法做防抖
       //这里有问题,只是对每个按钮的点击事件单独做了防抖,但是两个按钮之间做不到防抖的效果
       onClick1async function(){
           let res = await sendPost({username:'zs'age20})
           console.log('请求1的结果'res.data)
      },
       onClick2async function(){
           let res = await sendPost({username:'zs'age20})
           console.log('请求2的结果'res.data)
      },
  },
})
</script>
</html>

预览

步骤2-通过axios响应拦截器处理请求成功

通过axios的响应拦截器,在请求成功后在map对象当中,删除该请求信息的数据

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
   <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.min.js" type="application/javascript"></script>
   <script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/axios/0.26.0/axios.min.js" type="application/javascript"></script>
   <script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/qs/6.10.3/qs.js" type="application/javascript"></script>

</head>
<body>
   <div id="app">
       <button @click="onClick1" ref="btn1">请求1</button>
       <button @click="onClick2" ref="btn2">请求2</button>
   </div>
</body>
<script>
//存储请求信息和取消方法的的map对象    
const pendingRequest = new Map();  
//根据请求的信息(请求方式,url,请求get/post数据),产生map的key
function getRequestKey(config){
   const { methodurlparamsdata } = config;
   return [methodurlQs.stringify(params), Qs.stringify(data)].join("&");
}  
//请求拦截器
axios.interceptors.request.use(
   function (config) {
   //根据请求的信息(请求方式,url,请求get/post数据),产生map的key
   let requestKey = getRequestKey(config)
   //判断请求是否重复
   if(pendingRequest.has(requestKey)){
       //取消上次请求
       let cancel = pendingRequest.get(requestKey)
       cancel()
       //删除请求信息
       pendingRequest.delete(requestKey)
  }
   //把请求信息,添加请求到map当中
   // 生成取消方法
   config.cancelToken = config.cancelToken || new axios.CancelToken(cancel => {
       // 把取消方法添加到map
       if (!pendingRequest.has(requestKey)) {
           pendingRequest.set(requestKeycancel)
      }
  })
   return config;
},
(error=> {
    return Promise.reject(error);
}
);

//响应拦截器
axios.interceptors.response.use(
(response=> {
       //请求成功
       //删除请求的信息
       let requestKey = getRequestKey(response.config)
       if(pendingRequest.has(requestKey)){
           pendingRequest.delete(requestKey)  
      }
       return response;
  },
  (error=> {
       return Promise.reject(error);
  }
);
let sendPost = function(data){
   return axios({
       url'http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test',
       method'post',
       data
  })
}
new Vue({
   el'#app',
   mounted() {
       this.$refs.btn1.click()
       this.$refs.btn2.click()
  },
   methods: {
       // 使用lodash对请求方法做防抖
       //这里有问题,只是对每个按钮的点击事件单独做了防抖,但是两个按钮之间做不到防抖的效果
       onClick1async function(){
           let res = await sendPost({username:'zs'age20})
           console.log('请求1的结果'res.data)
      },
       onClick2async function(){
           let res = await sendPost({username:'zs'age20})
           console.log('请求2的结果'res.data)
      },
  },
})
</script>
</html>

预览

步骤3-通过axios响应拦截器处理请求失败

通过axios的响应拦截器,在请求失败后在map对象当中,删除该请求信息的数据

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
   <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.min.js" type="application/javascript"></script>
   <script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/axios/0.26.0/axios.min.js" type="application/javascript"></script>
   <script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/qs/6.10.3/qs.js" type="application/javascript"></script>

</head>
<body>
   <div id="app">
       <button @click="onClick1" ref="btn1">请求1</button>
       <button @click="onClick2" ref="btn2">请求2</button>
   </div>
</body>
<script>
//存储请求信息和取消方法的的map对象    
const pendingRequest = new Map();  
//根据请求的信息(请求方式,url,请求get/post数据),产生map的key
function getRequestKey(config){
   const { methodurlparamsdata } = config;
   return [methodurlQs.stringify(params), Qs.stringify(data)].join("&");
}  
//请求拦截器
axios.interceptors.request.use(
   function (config) {
   //根据请求的信息(请求方式,url,请求get/post数据),产生map的key
   let requestKey = getRequestKey(config)
   //判断请求是否重复
   if(pendingRequest.has(requestKey)){
       //取消上次请求
       let cancel = pendingRequest.get(requestKey)
       cancel()
       //删除请求信息
       pendingRequest.delete(requestKey)
  }
   //把请求信息,添加请求到map当中
   // 生成取消方法
   config.cancelToken = config.cancelToken || new axios.CancelToken(cancel => {
       // 把取消方法添加到map
       if (!pendingRequest.has(requestKey)) {
           pendingRequest.set(requestKeycancel)
      }
  })
   return config;
},
(error=> {
    return Promise.reject(error);
}
);
//删除请求信息
function delPendingRequest(config){
   let requestKey = getRequestKey(config)
   if(pendingRequest.has(requestKey)){
       pendingRequest.delete(requestKey)  
  }
}
//响应拦截器
axios.interceptors.response.use(
(response=> {
       //请求成功
       //删除请求的信息
       delPendingRequest(response.config)
       return response;
  },
  (error=> {
       //请求失败
       //不是取消请求的错误
       if (!axios.isCancel(error)){
           //服务器报400,500报错,删除请求信息
           delPendingRequest(error.config || {})
      }
       return Promise.reject(error);
  }
);
let sendPost = function(data){
   return axios({
       url'http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test',
       method'post',
       data
  })
}
new Vue({
   el'#app',
   mounted() {
       this.$refs.btn1.click()
       this.$refs.btn2.click()
  },
   methods: {
       // 使用lodash对请求方法做防抖
       //这里有问题,只是对每个按钮的点击事件单独做了防抖,但是两个按钮之间做不到防抖的效果
       onClick1async function(){
           let res = await sendPost({username:'zs'age20})
           console.log('请求1的结果'res.data)
      },
       onClick2async function(){
           let res = await sendPost({username:'zs'age20})
           console.log('请求2的结果'res.data)
      },
  },
})
</script>
</html>

预览

作者:黄金林
来源:juejin.cn/post/7189231050806001719

0 个评论

要回复文章请先登录注册