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!
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
(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
Methode 1 – Anti-Shake-Verarbeitung durch Timer
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-Tutoriallodash
的debounce
方法来简化防抖的代码 【相关推荐:vuejs视频教程、web前端开发】
<!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: 'https://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test', method: 'post', data }) } new Vue({ el: '#app', methods: { // 调用lodash的防抖方法debounce,实现连续点击按钮多次,0.3秒后调用1次接口 onClick: _.debounce(async function(){ let res = await sendPost({username:'zs', age: 20}) console.log('请求的结果', res.data) }, 300), }, }) </script> </html>
无法解决多个按钮件的重复请求的发送问题,例如下面两种情况
按钮事件间是相互独立的,调用的是不同方法,做不到按钮间防抖效果
<!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: '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对请求方法做防抖 //这里有问题,只是对每个按钮的点击事件单独做了防抖,但是两个按钮之间做不到防抖的效果 onClick1: _.debounce(async function(){ let res = await sendPost({username:'zs', age: 20}) console.log('请求1的结果', res.data) }, 300), onClick2: _.debounce(async function(){ let res = await sendPost({username:'zs', age: 20}) console.log('请求2的结果', res.data) }, 300), }, }) </script> </html>
按钮间调用的方法是相同的,是可以对方法做防抖处理,但是处理本身对方法做了一次封装,会影响到之前方法的返回值接收,需要对之前的方法做更多处理,变得更加复杂,不推荐
<!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: 'http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test', method: 'post', data }) }, 300) new Vue({ el: '#app', mounted() { this.$refs.btn1.click() this.$refs.btn2.click() }, methods: { onClick1: async function(){ //这里有问题,sendPost返回值不是promise,而是undefined let res = await sendPost({username:'zs', age: 20}) console.log('请求1的结果', res) }, onClick2: async function(){ let res = await sendPost({username:'zs', age: 20}) console.log('请求2的结果', res) }, }, }) </script> </html>
方式2-通过取消ajax请求
直接对请求方法做处理,通过ajax库的api方法把重复的请求给取消掉
通过调用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
的CancelToken
对象实例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('http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test', { params: {username: 'zs', age: 20}, cancelToken: source.token }).then(res=>{ console.log('res', res.data) }).catch(err=>{ console.log('err', 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('http://nodejs-cloud-studio-demo-bkzxs.nodejs-cloud-studio-demo.50185620.cn-hangzhou.fc.devsapp.net/test', { params: {username: 'zs', age: 20}, cancelToken: cancelToken }).then(res=>{ console.log('res', res.data) }).catch(err=>{ console.log('err', err) }) //在谷歌浏览器的低速3g下面测试 //通过调用cancelFn方法取消 setTimeout(() => cancelFn(), 100); </script> </html>
通过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: '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对请求方法做防抖 //这里有问题,只是对每个按钮的点击事件单独做了防抖,但是两个按钮之间做不到防抖的效果 onClick1: async function(){ let res = await sendPost({username:'zs', age: 20}) console.log('请求1的结果', res.data) }, onClick2: async function(){ let res = await sendPost({username:'zs', age: 20}) console.log('请求2的结果', res.data) }, }, }) </script> </html>
通过axios
, Web-Frontend-Entwicklung
<!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: '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对请求方法做防抖 //这里有问题,只是对每个按钮的点击事件单独做了防抖,但是两个按钮之间做不到防抖的效果 onClick1: async function(){ let res = await sendPost({username:'zs', age: 20}) console.log('请求1的结果', res.data) }, onClick2: async function(){ let res = await sendPost({username:'zs', age: 20}) console.log('请求2的结果', res.data) }, }, }) </script> </html>
<!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: '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对请求方法做防抖 //这里有问题,只是对每个按钮的点击事件单独做了防抖,但是两个按钮之间做不到防抖的效果 onClick1: async function(){ let res = await sendPost({username:'zs', age: 20}) console.log('请求1的结果', res.data) }, onClick2: async function(){ let res = await sendPost({username:'zs', age: 20}) console.log('请求2的结果', res.data) }, }, }) </script> </html>
abort
-Methode der XMLHttpRequest
-Objektinstanz aufrufen🎜rrreee🎜Vorschau 🎜 🎜 CancelToken
-Objektinstanz-cancel
-Methode von axios
Anfrage abbrechen🎜rrreee🎜Vorschau 🎜🎜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 🎜🎜axios
nach erfolgreicher Anforderung die Daten der Anforderungsinformationen im Kartenobjekt🎜rrreee🎜🎜Vorschau🎜🎜通过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: '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对请求方法做防抖 //这里有问题,只是对每个按钮的点击事件单独做了防抖,但是两个按钮之间做不到防抖的效果 onClick1: async function(){ let res = await sendPost({username:'zs', age: 20}) console.log('请求1的结果', res.data) }, onClick2: async function(){ let res = await sendPost({username:'zs', age: 20}) console.log('请求2的结果', res.data) }, }, }) </script> </html>
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!