Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue-阻止重复请求 #62

Open
PleaseStartYourPerformance opened this issue May 12, 2023 · 0 comments
Open

Vue-阻止重复请求 #62

PleaseStartYourPerformance opened this issue May 12, 2023 · 0 comments

Comments

@PleaseStartYourPerformance
Copy link
Owner

摘录自掘金链接:https://juejin.cn/post/7189231050806001719?utm_source=gold_browser_extension

背景

项目当中前端代码会遇到同一个请求向服务器发了多次的情况,我们要避免服务器资源浪费,同一个请求一定时间只允许发一次请求

思路

1.如果业务简单,例如同一个按钮防止多次点击,我们可以用定时器做防抖处理
2.如果业务复杂,例如多个组件通过代码,同一个请求发多次,这个时候防抖已经不好处理了,最好是对重复的ajax请求统一做取消操作

方式1-通过定时器做防抖处理

当用户连续点击多次同一个按钮,最后一次点击之后,过小段时间后才发起一次请求
原理:每次调用方法后都产生一个定时器,定时器结束以后再发请求,如果重复调用方法,就取消当前的定时器,创建新的定时器,等结束后再发请求,工作当中可以用第三方封装的工具函数例如lodash的debounce方法来简化防抖的代码

<!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/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>

测试链接:http://jsrun.net/UZcKp

问题:

无法解决多个按钮件的重复请求的发送问题,例如下面两种情况
情况-在点击事件上做防抖
按钮事件间是相互独立的,调用的是不同方法,做不到按钮间防抖效果

<!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/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>

demo链接:http://jsrun.net/9ZcKp

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

<!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/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>

链接:http://jsrun.net/eZcKp

方式2-通过取消ajax请求

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

原理:

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

<!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>
</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>

链接:http://jsrun.net/QZcKp

axios取消请求

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

<!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://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>

链接:http://jsrun.net/zZcKp

代码

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

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

<!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 { 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>

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

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

image

<!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 { 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>

链接:http://jsrun.net/EZcKp

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

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

image
image

<!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 { 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>

image

<!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://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/axios/0.26.0/axios.min.js" type="application/javascript"></script>
</head>
<body>
</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
    })
}
axios.interceptors.request.use(async function (config) {
    // 通过,config.adapter,允许自定义处理请求
    config.adapter = function (config) {
        return new Promise((resolve) => {
          const res = {
            data: 'hello',
            status: 200,
            statusText: 'OK',
            headers: { 'content-type': 'text/plain; charset=utf-8' },
            config,
            request: {}
          }
          return resolve(res)
        })
    }
    return config
})
;(function(){
    sendPost({username:'zs', age: 20}).then(res=>{
        console.log('res1',res.data)
    })
    sendPost({username:'zs', age: 20}).then(res=>{
        console.log('res2',res.data)
    })
})();
</script>
</html>

image

<!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>
// 缓存对象
let cache = {
    // 缓存列表
    list: [],
    // 最大缓存数
    MAX_NUM: 100,
    // 最大缓存时间
    EXPIRED_TIME: 60000,
    // 根据请求的信息(请求方式,url,请求get/post数据),产生map的key
    getRequestKey(config){
        const { method, url, params, data } = config;
        return [method, url, Qs.stringify(params), Qs.stringify(data)].join("&");
    },
    // 添加缓存结果
    add({config, data}){
        if(config.data) config.data = JSON.parse(config.data)
        let key = this.getRequestKey(config)
        let i = this.list.findIndex(t=>t.key === key)
        if(i>-1){
            // 保存请求结果
            this.list[i].data = data
            // 把结果给接口
            this.list[i].resolve(data)
        }else{
            // 添加到缓存列表中
            this.list.push({ time: Date.now(), key, data })
        }
    },
    // 查找缓存结果
    find(config){
        // 根据请求信息生成key
        let key = this.getRequestKey(config)
        let i = this.list.findIndex(t=>  t.key === key)
        // 判断缓存当中是否有该请求结果
        if(i>-1){
            let f = this.list[i]
            // 判断是否超出了最大缓存时间
            if(Date.now() - f.time > this.EXPIRED_TIME){
                // 清除该缓存
                this.list.splice(i, 1)
            }else{
                // 返回缓存
                return f
            }
        }
        // 添加缓存信息
        let t = {key, time: Date.now()}
        t.data = new Promise((resolve)=>{
            t.resolve = resolve
        })
        // 判断是否超出了最大缓存数量
        if(this.list.length === this.MAX_NUM){
            this.list.shift()
        }
        this.list.push(t)
        // 返回undefined,让请求拦截不执行config.adapter
        return undefined
    }
}   

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
    })
}
axios.interceptors.request.use(async function (config) {
    let f =  cache.find(config)
    // 查看缓存当中有没有
    if(f){
        // 通过config.adapter,允许自定义处理请求
        config.adapter = function (config) {
            return new Promise((resolve) => {
                const res = {
                    status: 200,
                    statusText: 'OK',
                    headers: { 'content-type': 'application/json; charset=utf-8' },
                    config,
                    request: {}
                }
                // 判断缓存当中data是否是Promise?
                //   如果是,代表数据正在获取中
                //   如果不是代表请求已经获取过
                if(f.data instanceof Promise){
                    f.data.then(data=>{
                        resolve({ ...res, data })
                    })
                }else{
                    resolve({ ...res, data: f.data })
                }
            })
        }
    }
    return config
})
axios.interceptors.response.use(
  (response) => {
        //请求成功
        //缓存结果到缓存中
        cache.add(response)
        return response;
   }
);

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>

链接:http://jsrun.net/xidKp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant