>  기사  >  웹 프론트엔드  >  이 글에서는 Vue가 반복 요청을 방지하는 방법에 대해 이야기해 보겠습니다.

이 글에서는 Vue가 반복 요청을 방지하는 방법에 대해 이야기해 보겠습니다.

青灯夜游
青灯夜游앞으로
2023-01-28 19:31:132871검색

vue는 어떻게 반복 요청을 방지하나요? 다음 글에서는 Vue가 반복 요청을 방지하는 두 가지 방법을 소개하겠습니다. 도움이 되길 바랍니다.

이 글에서는 Vue가 반복 요청을 방지하는 방법에 대해 이야기해 보겠습니다.

프로젝트의 프런트 엔드 코드는 동일한 요청이 서버에 여러 번 전송되는 상황에 직면하게 됩니다. 동일한 요청은 특정 기간에 한 번만 전송되도록 허용됩니다. of time

Thoughts

(1) 동일한 버튼을 여러 번 클릭하는 것을 방지하는 등 비즈니스가 간단한 경우 흔들림 방지 처리를 위해 타이머를 사용할 수 있습니다.
(2) 다음과 같이 비즈니스가 복잡한 경우 여러 구성 요소가 코드를 통과하고 동일한 요청이 여러 번 전송되는 경우 이미 흔들림 방지가 처리되어 있으므로 반복되는 Ajax 요청을 통일된 방식으로 취소하는 것이 가장 좋습니다

방법 1 - 타이머를 통한 흔들림 방지 처리

(a) 개요

효과 : 사용자가 동일한 버튼을 여러 번 연속 클릭하면 짧은 시간 후에 요청이 시작됩니다. 마지막 클릭 후 시간
Principle: 각 메소드가 호출된 후 타이머가 생성되고, 타이머가 만료된 후에 요청이 전송됩니다. 메소드를 반복적으로 호출하면 현재 타이머가 취소되고, 새 타이머를 만든 후 전송됩니다. lodashdebounce code> 메소드와 같은 타사 캡슐화된 도구 기능을 사용하여 흔들림 방지 코드를 단순화할 수 있습니다. [관련 권장 사항: <a href="https://www.php.cn/course/list/18.html" target="_blank" textvalue="vuejs 비디오 튜토리얼">vuejs 비디오 튜토리얼<code>lodashdebounce方法来简化防抖的代码  【相关推荐:vuejs视频教程web前端开发

(b)代码

<!DOCTYPE html>
<html>
<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/lodash.js/4.17.21/lodash.min.js" type="application/javascript"></script>
    <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>
</head>
<body>
    <div id="app">
        <button @click="onClick">请求</button>
    </div>
</body>
<script>
// 定义请求接口
function sendPost(data){
    return axios({
        url: &#39;https://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test&#39;,
        method: &#39;post&#39;,
        data
    })
}
new Vue({
    el: &#39;#app&#39;,
    methods: {
        // 调用lodash的防抖方法debounce,实现连续点击按钮多次,0.3秒后调用1次接口
        onClick: _.debounce(async function(){
            let res = await sendPost({username:&#39;zs&#39;, age: 20})
            console.log(&#39;请求的结果&#39;, res.data)
        }, 300),
    },
})
</script>
</html>

(c)预览

连接

(d)存在的问题

无法解决多个按钮件的重复请求的发送问题,例如下面两种情况

情况-在点击事件上做防抖

按钮事件间是相互独立的,调用的是不同方法,做不到按钮间防抖效果

<!DOCTYPE html>
<html>
<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/lodash.js/4.17.21/lodash.min.js" type="application/javascript"></script>
    <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>
</head>
<body>
    <div id="app">
        <button @click="onClick1" ref="btn1">请求1</button>
        <button @click="onClick2" ref="btn2">请求2</button>
    </div>
</body>
<script>
  
let sendPost = function(data){
    return axios({
        url: &#39;http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test&#39;,
        method: &#39;post&#39;,
        data
    })
}
new Vue({
    el: &#39;#app&#39;,
    mounted() {
        this.$refs.btn1.click()
        this.$refs.btn2.click()
    },
    methods: {
        // 使用lodash对请求方法做防抖
        //这里有问题,只是对每个按钮的点击事件单独做了防抖,但是两个按钮之间做不到防抖的效果
        onClick1: _.debounce(async function(){
            let res = await sendPost({username:&#39;zs&#39;, age: 20})
            console.log(&#39;请求1的结果&#39;, res.data)
        }, 300),
        onClick2: _.debounce(async function(){
            let res = await sendPost({username:&#39;zs&#39;, age: 20})
            console.log(&#39;请求2的结果&#39;, res.data)
        }, 300),
    },
})
</script>
</html>

预览

情况2-在接口方法做防抖

按钮间调用的方法是相同的,是可以对方法做防抖处理,但是处理本身对方法做了一次封装,会影响到之前方法的返回值接收,需要对之前的方法做更多处理,变得更加复杂,不推荐

<!DOCTYPE html>
<html>
<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/lodash.js/4.17.21/lodash.min.js" type="application/javascript"></script>
    <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>
</head>
<body>
    <div id="app">
        <button @click="onClick1" ref="btn1">请求1</button>
        <button @click="onClick2" ref="btn2">请求2</button>
    </div>
</body>
<script>
// 使用lodash对请求方法做防抖,    
let sendPost = _.debounce(function(data){
    //这里有问题,这里的返回值不能作为sendPost方法执行的返回值,因为debounce内部包裹了一层
    return axios({
        url: &#39;http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test&#39;,
        method: &#39;post&#39;,
        data
    })
}, 300)
new Vue({
    el: &#39;#app&#39;,
    mounted() {
        this.$refs.btn1.click()
        this.$refs.btn2.click()
    },
    methods: {
        onClick1: async function(){
            //这里有问题,sendPost返回值不是promise,而是undefined
            let res = await sendPost({username:&#39;zs&#39;, age: 20})
            console.log(&#39;请求1的结果&#39;, res)
        },
        onClick2: async function(){
            let res = await sendPost({username:&#39;zs&#39;, age: 20})
            console.log(&#39;请求2的结果&#39;, res)
        },
    },
})
</script>
</html>

预览

方式2-通过取消ajax请求

(a) 概述

直接对请求方法做处理,通过ajax库的api方法把重复的请求给取消掉

(b)原理

原生ajax取消请求

通过调用XMLHttpRequest对象实例的abort方法把请求给取消掉

<!DOCTYPE html>
<html>
<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>
</head>
<body>
</body>
<script>
//原生ajax的语法    
let xhr = new XMLHttpRequest();
xhr.open("GET", "http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test?username=zs&age=20", true);
xhr.onload = function(){
    console.log(xhr.responseText)
}
xhr.send();
//在谷歌浏览器的低速3g下面测试
//通过XMLHttpRequest实例的abort方法取消请求
setTimeout(() => xhr.abort(), 100);
</script>
</html>

预览

axios取消请求

通过axiosCancelToken对象实例cancel方法把请求给取消掉

<!DOCTYPE html>
<html>
<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://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/axios/0.26.0/axios.min.js" type="application/javascript"></script>
</head>
<body>
</body>
<script>
/*axios的取消的语法*/
// 方式1-通过axios.CancelToken.source产生cancelToken和cancel方法
/*
const source =  axios.CancelToken.source();
axios.get(&#39;http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test&#39;, {
    params: {username: &#39;zs&#39;, age: 20}, 
    cancelToken: source.token
}).then(res=>{
    console.log(&#39;res&#39;, res.data)
}).catch(err=>{
    console.log(&#39;err&#39;, err)
})
//在谷歌浏览器的低速3g下面测试
//通过调用source的cancel方法取消
setTimeout(() => source.cancel(), 100);
*/

/**/
// 方式2-通过new axios.CancelToken产生cancelToken和cancel方法
let cancelFn 
const cancelToken =  new axios.CancelToken(cancel=>{
    cancelFn = cancel
});
axios.get(&#39;http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test&#39;, {
    params: {username: &#39;zs&#39;, age: 20}, 
    cancelToken: cancelToken
}).then(res=>{
    console.log(&#39;res&#39;, res.data)
}).catch(err=>{
    console.log(&#39;err&#39;, err)
})
//在谷歌浏览器的低速3g下面测试
//通过调用cancelFn方法取消
setTimeout(() => cancelFn(), 100);

</script>
</html>

预览

(c)代码

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

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

<!DOCTYPE html>
<html>
<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 { method, url, params, data } = config;
    return [method, url, Qs.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(requestKey, cancel)
        }
    })
    return config;
  },
  (error) => {
     return Promise.reject(error);
  }
);
let sendPost = function(data){
    return axios({
        url: &#39;http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test&#39;,
        method: &#39;post&#39;,
        data
    })
}
new Vue({
    el: &#39;#app&#39;,
    mounted() {
        this.$refs.btn1.click()
        this.$refs.btn2.click()
    },
    methods: {
        // 使用lodash对请求方法做防抖
        //这里有问题,只是对每个按钮的点击事件单独做了防抖,但是两个按钮之间做不到防抖的效果
        onClick1: async function(){
            let res = await sendPost({username:&#39;zs&#39;, age: 20})
            console.log(&#39;请求1的结果&#39;, res.data)
        },
        onClick2: async function(){
            let res = await sendPost({username:&#39;zs&#39;, age: 20})
            console.log(&#39;请求2的结果&#39;, res.data)
        },
    },
})
</script>
</html>

预览

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

通过axios, 웹 프론트엔드 개발

(b) 코드
<!DOCTYPE html>
<html>
<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 { method, url, params, data } = config;
    return [method, url, Qs.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(requestKey, cancel)
        }
    })
    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: &#39;http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test&#39;,
        method: &#39;post&#39;,
        data
    })
}
new Vue({
    el: &#39;#app&#39;,
    mounted() {
        this.$refs.btn1.click()
        this.$refs.btn2.click()
    },
    methods: {
        // 使用lodash对请求方法做防抖
        //这里有问题,只是对每个按钮的点击事件单独做了防抖,但是两个按钮之间做不到防抖的效果
        onClick1: async function(){
            let res = await sendPost({username:&#39;zs&#39;, age: 20})
            console.log(&#39;请求1的结果&#39;, res.data)
        },
        onClick2: async function(){
            let res = await sendPost({username:&#39;zs&#39;, age: 20})
            console.log(&#39;请求2的结果&#39;, res.data)
        },
    },
})
</script>
</html>

(c) 미리보기🎜🎜Connection🎜🎜

(d)이 존재합니다. 문제 🎜🎜는 여러 요청을 반복적으로 보내는 문제를 해결할 수 없습니다. 다음 두 가지 상황과 같은 버튼 부분 🎜

상황 - 클릭 이벤트 시 흔들림 방지

🎜Button 이벤트는 서로 독립적이며 서로 다른 메소드를 호출하므로 버튼 사이의 흔들림 방지 효과를 얻을 수 없습니다🎜
<!DOCTYPE html>
<html>
<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 { method, url, params, data } = config;
    return [method, url, Qs.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(requestKey, cancel)
        }
    })
    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: &#39;http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test&#39;,
        method: &#39;post&#39;,
        data
    })
}
new Vue({
    el: &#39;#app&#39;,
    mounted() {
        this.$refs.btn1.click()
        this.$refs.btn2.click()
    },
    methods: {
        // 使用lodash对请求方法做防抖
        //这里有问题,只是对每个按钮的点击事件单独做了防抖,但是两个按钮之间做不到防抖的效果
        onClick1: async function(){
            let res = await sendPost({username:&#39;zs&#39;, age: 20})
            console.log(&#39;请求1的结果&#39;, res.data)
        },
        onClick2: async function(){
            let res = await sendPost({username:&#39;zs&#39;, age: 20})
            console.log(&#39;请求2的结果&#39;, res.data)
        },
    },
})
</script>
</html>
🎜
미리보기 🎜🎜

사례 2 - 인터페이스 방법에서 수행 Anti-shake

🎜방법 버튼 사이에 호출되는 것은 동일합니다. 메소드에 대해 손떨림 방지 처리를 수행할 수 있지만 처리 자체가 메소드를 캡슐화하므로 이전 메소드의 반환 값 수신에 영향을 미칩니다. 이전 방법은 더 많은 처리를 수행하고 더 복잡해지며 🎜권장되지 않습니다🎜🎜rrreee🎜
Preview🎜🎜🎜🎜🎜방법 2 - Ajax 요청 취소🎜🎜🎜

( a) 개요🎜🎜 요청 방식을 직접 처리하고, ajax 라이브러리의 api 방식을 통해 중복 요청을 취소합니다🎜

(b) 원리🎜

네이티브 Ajax 취소 요청

🎜XMLHttpRequest 개체 인스턴스의 abort 메서드를 호출하여 요청을 취소하세요🎜rrreee🎜
미리보기 🎜 🎜

axios 취소 요청

🎜 axiosCancelToken 객체 인스턴스 cancel 메서드를 통해 > 요청 취소🎜rrreee🎜
미리보기 🎜🎜

(c) 코드 🎜

1단계 - axios를 통해 요청 인터셉터는 반복되는 요청을 취소합니다

🎜axios를 통해 인터셉터를 요청하고, 각 요청 전에 요청 정보와 요청한 취소 메서드를 맵 객체에 넣고 맵 객체가 이루어졌는지 여부를 확인합니다. 업로드 취소 요청이 있는 경우🎜rrreee🎜
미리보기 🎜🎜

2단계 - Axios 응답 인터셉터를 통한 요청 처리 성공

🎜 axios의 응답 인터셉터를 통해 요청 성공 후 맵 객체에 있는 요청 정보의 데이터를 삭제합니다🎜rrreee🎜🎜Preview🎜🎜

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

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

<!DOCTYPE html>
<html>
<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 { method, url, params, data } = config;
    return [method, url, Qs.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(requestKey, cancel)
        }
    })
    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: &#39;http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test&#39;,
        method: &#39;post&#39;,
        data
    })
}
new Vue({
    el: &#39;#app&#39;,
    mounted() {
        this.$refs.btn1.click()
        this.$refs.btn2.click()
    },
    methods: {
        // 使用lodash对请求方法做防抖
        //这里有问题,只是对每个按钮的点击事件单独做了防抖,但是两个按钮之间做不到防抖的效果
        onClick1: async function(){
            let res = await sendPost({username:&#39;zs&#39;, age: 20})
            console.log(&#39;请求1的结果&#39;, res.data)
        },
        onClick2: async function(){
            let res = await sendPost({username:&#39;zs&#39;, age: 20})
            console.log(&#39;请求2的结果&#39;, res.data)
        },
    },
})
</script>
</html>

预览

(学习视频分享:vuejs入门教程编程基础视频

위 내용은 이 글에서는 Vue가 반복 요청을 방지하는 방법에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제