Bagaimanakah vue menghalang permintaan berulang? Artikel berikut akan memperkenalkan dua cara untuk Vue menghalang permintaan berulang saya harap ia akan membantu anda!
Kod bahagian hadapan dalam projek akan menghadapi situasi di mana permintaan yang sama dihantar ke pelayan berkali-kali Kita mesti mengelakkan pembaziran sumber pelayan hanya dibenarkan dihantar sekali dalam tempoh masa tertentu Permintaan
(1) Jika perniagaan itu mudah, seperti menghalang berbilang klik pada perkara yang sama. butang, kita boleh menggunakan pemasa untuk pemprosesan anti goncang
(2 ) Jika perniagaan adalah kompleks, contohnya, berbilang komponen melalui kod dan permintaan yang sama dihantar beberapa kali, anti goncang tidak lagi mudah dikendalikan pada masa ini adalah lebih baik untuk membatalkan permintaan ajax berulang dengan cara yang bersatu
Kaedah 1 - Pemprosesan anti goncang melalui pemasa
Kesan: Apabila pengguna mengklik butang yang sama beberapa kali berturut-turut, permintaan akan dimulakan selepas tempoh masa yang singkat selepas klik terakhir
Prinsip: Setiap kali kaedah dipanggil Pemasa dijana pada penghujung, dan permintaan dihantar selepas pemasa tamat tempoh kaedah dipanggil berulang kali, pemasa semasa akan dibatalkan, pemasa baharu akan dibuat, dan permintaan akan dihantar selepas pemasa tamat Anda boleh menggunakan fungsi alat berkapsul pihak ketiga sebagai contoh, lodash
menggunakan kaedah debounce
untuk memudahkan kod anti goncang [Cadangan berkaitan: tutorial video vuejs, pembangunan bahagian hadapan 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>
Tidak Dapat Menyelesaikan masalah menghantar permintaan berulang untuk berbilang komponen butang, seperti dua situasi berikut
Acara butang adalah bebas antara satu sama lain, dan panggilan adalah berbeza Kaedah , kesan anti goncang antara butang tidak boleh dicapai
<!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>
Panggilan antara butang Kaedah adalah sama Ia adalah mungkin untuk melakukan pemprosesan anti-goncang pada kaedah, tetapi pemprosesan itu sendiri merangkumi kaedah, yang akan menjejaskan penerimaan nilai pulangan kaedah sebelumnya dilakukan pada kaedah sebelumnya, yang menjadi lebih rumit Tidak disyorkan
<!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>
Kaedah 2 - Dengan membatalkan permintaan ajax
Proses kaedah permintaan secara langsung dan batalkan permintaan pendua melalui kaedah api perpustakaan ajax
Batalkan permintaan dengan memanggil XMLHttpRequest
kaedah abort
contoh objek
<!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>
Batalkan permintaan melalui axios
contoh objekCancelToken
kaedah 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>
Melalui axios
pemintas permintaan, letakkan maklumat permintaan dan kaedah pembatalan permintaan sebelum setiap permintaan Dalam objek peta, dan tentukan sama ada permintaan untuk maklumat yang diminta sudah wujud dalam objek peta, jika terdapat permintaan untuk membatalkan muat naik
<!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>
Melalui pemintas respons axios
, selepas permintaan berjaya, data maklumat permintaan dipadamkan dalam objek peta
<!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>
通过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>
Atas ialah kandungan terperinci Mari kita bincangkan tentang cara vue menghalang permintaan berulang dalam artikel ini. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!