代理模式
设计模式的概念都是较为抽象的,下面通过几个实例展示代理模式的实际应用
-
虚拟代理:常见
-
保护代理
保护代理比较少见,比如后台提供的上传图片接口
uploadImg
,后台接受请求后,在uploadImg
中过滤gif
格式的图片,如果是预期的图片格式,那么调用真正的保存图片方法saveImage
这种可以理解为保护代理。
代理模式的实际应用
函数节流
const throttle = (fn, wait) => {
let startTime = Date.now();
return function() {
if(Date.now() - startTime > wait) {
fn.apply(null,arguments)
startTime = Date.now();
}
}
}
function handleScroll() {
// 获取滚动位置
let pos = document.documentElement.scrollTop || document.body.scrollTop
console.log(`当前滚动位置:${pos}`)
}
// window.addEventListener('scroll', handleScroll)
window.addEventListener('scroll', throttle(handleScroll, 500))
函数防抖
const debounce = (fn,wait) => {
let timer;
return function() {
if(timer) clearInterval(timer);
timer = setTimeout(fn, wait);
}
}
function handleInput() {
console.log('发送校验请求')
}
// document.querySelector('input').addEventListener('input', handleInput)
document.querySelector('input')
.addEventListener('input', debounce(handleInput,1000)) // 输入一秒后发送校验请求
设置占位图
const myImage = (function () {
const img = new Image();
document.querySelector('.img-wrapper').appendChild(img)
return {
setSrc: function (src) {
img.src = src
}
}
})()
const loadingImge = './assets/loading.gif'
const realSrc = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581861147636&di=c751d2a6684f214552678cceea436c3c&imgtype=0&src=http%3A%2F%2Fattach.bbs.miui.com%2Fforum%2F201312%2F06%2F211410sxjtbyaj9abo5qzh.jpg"
const proxyImage = (function () {
const img = new Image()
img.onload = function () {
myImage.setSrc(this.src)
}
return {
setSrc: function (src) {
myImage.setSrc(loadingImge)
img.src = src
}
}
})()
// myImage.setSrc(realSrc)
proxyImage.setSrc(realSrc)
虚拟代理合并请求
点击页面上的
checkbox
发送选中的音频文件,实现类似于函数防抖,但区别在于定时器的使用以及清空时机。
代理模式通用实现
结合上面几个实例可以看到要实现代理模式一般需要两个函数fnA
和fnB
,其中fnB
是实现真正的功能,但我们不直接使用fnB
而是使用fnA
,在fnA
中引用了函数fnB
,何时调用fnB
取决于具体的需求或者优化策略。
可以看到通过代理模式,我们能对代码实现优化比如防抖节流和合并请求等