JS设计模式-代理模式

JS设计模式-代理模式

在前端的一些表格里,往往会有一些复选的批量操作,比如给用户批量赋予权限,由于涉及表格分页以及反复翻页的勾选重现,很多时候,都是点击复选框后就像后台发起请求,直接进行数据的持久化。但是这时候就有个问题了,只要我的手速足够快,这种向后台发起请求的频率是非常高的,而我作为LOL的黄金分段玩家,也有自信一秒钟点五个复选框,为此,我们需要一个代理来拦截一下这种高频操作。

首先我们模拟向后台发请求的方法,很简单:

function ajaxRes(id) {
  console.log(`请求参数id为${id}`);
}

如果我模拟点击了五次:

proxyRes(1)
proxyRes(2)
proxyRes(3)
proxyRes(4)
proxyRes(5)

控制台会模拟发了五次请求:

请求参数id为1
请求参数id为2
请求参数id为3
请求参数id为4
请求参数id为5

为此我们希望在一定时间内的频繁操作会缓存起来,暂时不向后台请求。

所以代理函数如下:

function proxyRes() {
    let timer = null;
    let cache = []

    return function(id) {
        cache.push(id);
        // 如果timer不为空,也就是还在两秒内,就直接返回。
        if (timer) {
            return
        }

        timer = setTimeout(() => {
            // 向后台发请求
            ajaxRes(cache);
            // 清除计时
            clearTimeout(timer);
            timer = null;
            // 清空缓存数组
            cache.length = 0;
        }, 2000);
    }
}

我们利用函数的作用域,设定了timer来记录操作时间,在第一次点击后的两秒内,都不会往后台发请求。而在这期间的操作,都放在了缓存cache里,如此就会大大减轻服务器的压力。

const prox = proxyRes()
prox(1)
prox(2)
prox(3)
prox(4)
prox(5)

// 请求参数id为1,2,3,4,5

这回在控制台只会打印一条请求信息了。

在以往的操作中我们的流程是这样的

用户
接口函数

现在变成了

用户
代理函数
接口函数

如果你看过我的其他文章,你会发现这和函数节流的结构非常像。你也可能会有疑问,我明明一个函数就能写完的东西,为什么非得拆成两个函数。因为我们代理函数的作用往往不会只代理这一个,上面的方法我们可以进一步改造:

function ajaxRes(id) {
    console.log(`请求参数id为${id}`);
}

// 注意这里参数变成了一个函数
function proxyRes(fn) {
    let timer = null;
    let cache = []

    return function(id) {
        cache.push(id);
        if (timer) {
            return
        }
		// 这里执行了传入的函数
        timer = setTimeout(() => {
            fn(cache);
            clearTimeout(timer);
            timer = null;
            cache.length = 0;
        }, 2000);
    }
}

// 使用的时候需要传入被代理的函数
const prox = proxyRes(ajaxRes)
prox(1)
prox(2)
prox(3)
prox(4)
prox(5)

这样其他的复选操作我们也可以一同代理了,我们也可以进一步理解代理的作用,就是为本体函数加一层缓存或者过滤。


ES6中有一个代理器对象Proxy,通过它我们可以实现对一些对象属性的监控、过滤。

比如我们要监测一个对象的属性,一旦它发生了改变,就要执行一些操作。

// 定义一个对象
const obj = {now: '2020/01/01'}
// 设置代理对象pro,代理的就是第一个参数obj,这里监控的是setter
const pro = new Proxy(obj, {
    // 第一个参数是目标对象,这里就是obj。第二个参数是对象的key。第三个是进行赋值操作时的新值
    set: function(target, key, val){
        // 如果值改变了,就会执行
        console.log(`${key}被修改了,旧的的值为${target[key]},新的值是${val}`);
        // 由于操作的是代理对象,真正要对obj进行赋值,需要下面的操作,其等同于target[key] = val。或者是Object.set
        Reflect.set(target, key, val)
    }
})

// 修改now的值,注意这里操作的是代理对象,而不是obj,操作obj并不会出发代理的监测
pro.now = new Date().toLocaleDateString()

一旦now的值发生改变,控制台就会输出

now被修改了,旧的的值为2020/01/01,新的值是2021/9/9

有了Proxy,我们就可以进一步的对对象内部属性进行校验、监控、监测了。

你可能感兴趣的:(JavaScript设计模式,javascript)