Vue + Axios全局接口防抖、节流封装实现
Vue + Axios全局接口防抖、节流封装实现
你是否在项目中会遇到过?
在项目中按钮点击做防连点?在请求一个接口中防止一个接口被多次请求?或者你要做一个点赞,防止那种坏坏的人,多次点击,疯狂点击........等一系列类似的问题。
如果有!!!!!!
那么你就要往下读此文章了。
什么是接口防抖和节流?
接口防抖(Debouncing)和节流(Throttling)是前端开发中常用的技术,用于限制和控制事件触发频率。
- 接口防抖(Debouncing):
接口防抖是指在事件被触发后,延迟一段时间执行相应的操作,如果在延迟时间内再次触发了该事件,则重新计时。防抖的目的是减少事件触发频率,避免在短时间内多次触发事件而导致多次执行相应的操作。常见的应用场景包括搜索框输入联想、窗口大小调整等需要限制频率的场景。 - 接口节流(Throttling):
接口节流是指在一定时间间隔内,只允许事件触发一次,即使在该时间间隔内多次触发该事件,也只会执行一次相应的操作。节流的目的是控制事件触发频率,避免在短时间内多次触发事件而导致过多的资源消耗。常见的应用场景包括滚动加载、按钮点击等需要限制频率的场景。
接口防抖和节流都是为了在频繁触发事件时提供优化和控制的机制。它们可以帮助提高前端应用的性能和用户体验,减少不必要的请求和操作,避免过度消耗资源。具体选择使用哪种方式,取决于具体的应用场景和需求。
Vue + Axios 封装全局接口防抖和节流配置
在 Vue 中,可以通过创建一个全局的 axios
实例来封装接口请求。下面我们将根据需求,对 axios
实例进行编写,实现防抖和节流功能。
防抖
在实现防抖之前,我们先来介绍一下什么是“防抖”。在前端开发中,“防抖”指的是在一定时间内只能触发一次事件,通常是输入框或滚动事件。假如没有防抖控制,页面会出现一些异常情况,例如:搜索框输入过快、滚动条跳动频繁等。
防抖的实现原理非常简单,就是通过对要执行的函数进行延迟处理,以此来控制函数执行的次数。具体流程如下:
- 定义一个变量用于保存计时器。
- 在函数执行前判断计时器是否存在,如果存在则清除计时器。
- 为函数设置时间延迟,将返回结果保存到计时器变量中。
- 等待时间超过设定的阈值后,执行相应的回调函数。
下面是防抖代码的示例:
// 防抖
function debounce(fn, delay = 500) {
let timer = null;
return function(...args) {
if (timer !== null) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, delay);
};
}
注意事项
在使用防抖技术的时候,需要注意以下几点:
- 时间延迟需要根据业务需求进行调整。
- 在防抖过程中,要确保函数参数传递正确。
节流
相比于防抖技术,节流技术更加灵活。在前端开发中,“节流”通常指的是在一定时间内只能执行一次事件,例如:下拉加载更多、页面滚动等。
实现原理
节流技术的实现原理也非常简单,就是通过设置一个固定时间间隔,在这个时间间隔内只能执行一次相应的回调函数。具体流程如下:
- 定义一个变量用于保存上一次执行函数的时间。
- 在执行函数前获取当前的时间戳。
- 判断当前时间与上一次执行时间是否大于设定的间隔时间,如果大于,则执行相应的回调函数,并更新上一次执行时间。
- 如果小于设定的间隔时间,则等待下一次执行。
下面是节流代码的示例:
// 节流
function throttle(fn, delay = 500) {
let last = 0;
return function(...args) {
let now = new Date().getTime();
if (now - last > delay) {
last = now;
fn.apply(this, args);
}
};
}
一个完整示例
import axios from 'axios'
function request(config) {
const instance = axios.create({
baseURL: 'http://localhost:3000/api',
timeout: 10000
})
// 防抖
const debounceTokenCancel = new Map()
instance.interceptors.request.use(config => {
const tokenKey = `${config.method}-${config.url}`
const cancel = debounceTokenCancel.get(tokenKey)
if (cancel) {
cancel()
}
return new Promise(resolve => {
const timer = setTimeout(() => {
clearTimeout(timer)
resolve(config)
}, 800)
debounceTokenCancel.set(tokenKey, () => {
clearTimeout(timer)
resolve(new Error('取消请求'))
})
})
}, error => {
console.log(error)
return Promise.reject(error)
})
instance.interceptors.response.use(response => {
return response
}, error => {
console.log(error)
return Promise.reject(error)
})
// 节流
let lastTime = new Date().getTime()
instance.interceptors.request.use(config => {
const nowTime = new Date().getTime()
if (nowTime - lastTime < 1000) {
return Promise.reject(new Error('节流处理中,稍后再试'))
}
lastTime = nowTime
return config
}, error => {
console.log(error)
return Promise.reject(error)
})
return instance(config)
}
export default request
以上来自于网络作者
作者:ShihHsing
链接:https://juejin.cn/post/7225133152490160187
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
下面我们来看看我们从chatGPT上的回答:
- 创建一个新的文件(例如
api.js
),用于封装Axios请求:
import axios from 'axios';
const instance = axios.create({
baseURL: 'your_base_url_here',
timeout: 5000, // 设置请求超时时间
});
// 全局的接口防抖
let debounceTimer = null;
function debounce(func, delay) {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(func, delay);
}
// 全局的接口节流
let throttleTimer = null;
let lastRequestTime = 0;
function throttle(func, delay) {
const currentTime = Date.now();
const remainingTime = delay - (currentTime - lastRequestTime);
clearTimeout(throttleTimer);
if (remainingTime <= 0) {
func();
lastRequestTime = currentTime;
} else {
throttleTimer = setTimeout(func, remainingTime);
}
}
// 封装get请求
function get(url, config) {
return instance.get(url, config);
}
// 封装post请求
function post(url, data, config) {
return instance.post(url, data, config);
}
export default {
debounce,
throttle,
get,
post,
};
- 在Vue的入口文件(例如
main.js
)中,全局注册api.js
中封装的方法:
import Vue from 'vue';
import api from './api.js';
Vue.prototype.$api = api;
现在,你可以在Vue组件中使用全局的接口防抖和节流方法了。下面是一个示例:
<template>
<div>
<button @click="debounceRequest">Debounce Request</button>
<button @click="throttleRequest">Throttle Request</button>
</div>
</template>
<script>
export default {
methods: {
debounceRequest() {
this.$api.debounce(() => {
// 在这里执行需要防抖的请求
}, 500);
},
throttleRequest() {
this.$api.throttle(() => {
// 在这里执行需要节流的请求
}, 500);
},
},
};
</script>
这样,当按钮被点击时,请求将会被防抖或节流,根据需要调整防抖和节流的时间间隔。请确保根据实际需求进行配置和调整。
这只是一种封装实现的方式,你可以根据具体项目的需求进行修改和扩展。希望对你的前端开发有所帮助!
当然你可能看出来他对于api.js
的封装不是太完美,那么我们继续对他进行提问:
我想让headers有一个固定的内容,通过请求,如果不传就用固定的,传了采用传递的值
import axios from 'axios';
const instance = axios.create({
baseURL: 'your_base_url_here',
timeout: 5000, // 设置请求超时时间
});
// 全局的接口防抖
let debounceTimer = null;
function debounce(func, delay) {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(func, delay);
}
// 全局的接口节流
let throttleTimer = null;
let lastRequestTime = 0;
function throttle(func, delay) {
const currentTime = Date.now();
const remainingTime = delay - (currentTime - lastRequestTime);
clearTimeout(throttleTimer);
if (remainingTime <= 0) {
func();
lastRequestTime = currentTime;
} else {
throttleTimer = setTimeout(func, remainingTime);
}
}
// 封装get请求
function get(url, params, config = {}) {
const defaultHeaders = {
'Content-Type': 'application/json', // 设置默认的请求头
// 添加其他默认请求头字段...
};
const headers = config.headers ? { ...defaultHeaders, ...config.headers } : defaultHeaders;
return instance.get(url, {
...config,
headers,
params,
});
}
// 封装post请求
function post(url, data, config = {}) {
const defaultHeaders = {
'Content-Type': 'application/json', // 设置默认的请求头
// 添加其他默认请求头字段...
};
const headers = config.headers ? { ...defaultHeaders, ...config.headers } : defaultHeaders;
return instance.post(url, data, {
...config,
headers,
});
}
// 封装put请求
function put(url, data, config = {}) {
const defaultHeaders = {
'Content-Type': 'application/json', // 设置默认的请求头
// 添加其他默认请求头字段...
};
const headers = config.headers ? { ...defaultHeaders, ...config.headers } : defaultHeaders;
return instance.put(url, data, {
...config,
headers,
});
}
// 封装delete请求
function del(url, config = {}) {
const defaultHeaders = {
'Content-Type': 'application/json', // 设置默认的请求头
// 添加其他默认请求头字段...
};
const headers = config.headers ? { ...defaultHeaders, ...config.headers } : defaultHeaders;
return instance.delete(url, {
...config,
headers,
});
}
export default {
debounce,
throttle,
get,
post,
put,
del,
};
当然我还问了一些其他的问题,这里就不一一列举出来了。所以小伙伴们,我们在尽可能理想的情况下,尽量对我们的封装去进行拓宽和完善来达到它的健壮!