Heim  >  Artikel  >  Web-Frontend  >  Lassen Sie uns in diesem Artikel darüber sprechen, wie Vue wiederholte Anfragen verhindert

Lassen Sie uns in diesem Artikel darüber sprechen, wie Vue wiederholte Anfragen verhindert

青灯夜游
青灯夜游nach vorne
2023-01-28 19:31:132893Durchsuche

Wie verhindert Vue wiederholte Anfragen? Der folgende Artikel stellt zwei Möglichkeiten für Vue vor, um wiederholte Anfragen zu verhindern. Ich hoffe, er ist hilfreich für Sie!

Lassen Sie uns in diesem Artikel darüber sprechen, wie Vue wiederholte Anfragen verhindert

Der Front-End-Code im Projekt wird auf die Situation stoßen, dass dieselbe Anfrage mehrmals an den Server gesendet wird. Wir müssen vermeiden, dass Serverressourcen verschwendet werden. Dieselbe Anfrage darf nur einmal in einem bestimmten Zeitraum gesendet werden der Zeit

Gedanken

(1) Wenn das Geschäft einfach ist, wie z. B. das Verhindern mehrerer Klicks auf dieselbe Schaltfläche, können wir einen Timer für die Anti-Shake-Verarbeitung verwenden
(2) Wenn das Geschäft komplex ist, wie z Mehrere Komponenten durchlaufen den Code und dieselbe Anfrage wird mehrmals gesendet. Anti-Shake wurde zu diesem Zeitpunkt bereits verarbeitet. Es ist schwierig damit umzugehen. Es ist am besten, die wiederholten Ajax-Anfragen auf einheitliche Weise abzubrechen

, um dies zu erreichen

Methode 1 – Anti-Shake-Verarbeitung durch Timer

(a) Übersicht

Wirkung : Wenn der Benutzer mehrmals hintereinander auf dieselbe Schaltfläche klickt, wird nach kurzer Zeit eine Anfrage initiiert nach dem letzten Klick
Prinzip: Nach dem Aufruf jeder Methode wird ein Timer generiert und die Anforderung wird nach Ablauf des Timers gesendet. Wenn durch wiederholtes Aufrufen der Methode der aktuelle Timer abgebrochen wird, erstellen Sie einen neuen Timer und senden Sie ihn dann Anfrage nach dem Ende. Sie können gekapselte Toolfunktionen von Drittanbietern wie die debounce code>-Methode von <code>lodash verwenden, um den Anti-Shake-Code zu vereinfachen [Verwandte Empfehlungen: vuejs-Video-Tutoriallodashdebounce方法来简化防抖的代码  【相关推荐: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, Web-Frontend-Entwicklung

(b) Code
<!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) Vorschau🎜🎜Connection🎜🎜

(d) existiert Das Problem 🎜🎜 kann das Problem des wiederholten Sendens von Anfragen für mehrere Schaltflächen nicht lösen Teile, wie die folgenden zwei Situationen 🎜

Situation – Anti-Shake-on-Click-Ereignis

🎜Button Die Ereignisse sind unabhängig voneinander und rufen unterschiedliche Methoden auf, also die Anti -Shake-Effekt zwischen Schaltflächen kann nicht erreicht werden🎜
<!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>
🎜
Vorschau 🎜🎜

Fall 2 – Machen Sie es in der Schnittstellenmethode Anti-Shake

🎜Die aufgerufenen Methoden Es ist möglich, eine Anti-Shake-Verarbeitung für die Methode durchzuführen, aber die Verarbeitung selbst kapselt die Methode, was sich auf den Rückgabewertempfang der vorherigen Methode auswirkt Vorherige Methode. Führen Sie mehr Verarbeitung durch, werden Sie komplexer, 🎜nicht empfohlen🎜🎜rrreee🎜 = "http://jsrun.net/eZcKp/edit" ref="nofollow noopener noreferrer">Vorschau🎜🎜🎜🎜🎜Methode 2 – Durch Abbrechen der Ajax-Anfrage🎜🎜🎜

(a) Übersicht🎜🎜 Verarbeiten Sie die Anforderungsmethode direkt und stornieren Sie doppelte Anforderungen über die API-Methode der Ajax-Bibliothek🎜

(b) Prinzip🎜

Native Ajax-Abbruchanforderung

🎜Brechen Sie die Anforderung ab, indem Sie die abort-Methode der XMLHttpRequest-Objektinstanz aufrufen🎜rrreee🎜
Vorschau 🎜 🎜

Axios-Stornierungsanfrage

🎜Über die CancelToken-Objektinstanz-cancel-Methode von axios Anfrage abbrechen🎜rrreee🎜
Vorschau 🎜🎜

(c) Code 🎜

Schritt 1 – Anfrage über axios Der Interceptor bricht wiederholte Anfragen ab

🎜Fordern Sie den Interceptor über axios an, fügen Sie die Anfrageinformationen und die angeforderte Abbruchmethode vor jeder Anfrage in ein Kartenobjekt ein und bestimmen Sie, ob das Kartenobjekt vorhanden ist für diese Anforderungsinformationen. Wenn eine Anfrage zum Abbrechen des Uploads vorliegt🎜rrreee🎜
Vorschau 🎜🎜

Schritt 2 – Anforderungsverarbeitung durch Axios Response Interceptor erfolgreich

🎜 Löschen Sie über den Antwort-Interceptor von axios nach erfolgreicher Anforderung die Daten der Anforderungsinformationen im Kartenobjekt🎜rrreee🎜🎜Vorschau🎜🎜

步骤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入门教程编程基础视频

Das obige ist der detaillierte Inhalt vonLassen Sie uns in diesem Artikel darüber sprechen, wie Vue wiederholte Anfragen verhindert. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen