请节约你的请求-代理模式
What's the proxy pattern?代理模式其实就是将违反单一性原则的类给抽离出来,尽量满足开放和封闭的原则。 相当于一个类的行为只是一种,但是你可以给这个类添加额外的行为。比如: 一个工厂制造伞,你可以给这个工厂设置一个代理,提供订单,运货,淘宝网店等多种行为。当然,里面还有最关键的一点就是,这个代理能把一些骗纸和忽悠都过滤掉,将最真实最直接的订单给工厂,让工厂能够放心的让工人加班,顺利的发年终奖. 图片延迟加载图片延迟加载是指,图片的加载应该在页面全部加载完后,再去加载。这样能够提高加载的速度和网页的体验性。实际操作就是,将原来网页的src独立出来,将原来图片使用一个loading.gif代替,然后再js里面手动创建个img去加载这个src,当加载完后把src替换就可以了。 var delayload = (function(){ var img = document.querySelector("#img"); img.src = "loading.gif"; var newImg = document.createElement("img"); newImg.onload = function(){ img.src = newImg.src; } return function(src){ newImg.src = src; } })(); delayload("jimmy.jpg"); 这样写,我给满分(在没有产经这个生物的前提下). //将背景图设置,和图片加载的src修改分开 var delayload = (function(){ var img = document.querySelector("#img"); return { setSrc:function(src){ img.src = src; } } })(); var proxy = (function(){ var img = document.createElement('img'); img.onload = function(){ delayload.setSrc(img.src); } return { setSrc:function(src){ delayload.setSrc("loading.gif"); img.src = src; } } })(); proxy.setSrc("jimmy.jpg"); 恩,如果产经要求换图片,好解决,换一下loading.gif就over了.如果产经要求换成纯色的。也行。 再加一个方法. var delayload = (function(){ var img = document.querySelector("#img"); return { setSrc:function(src){ img.src = src; },setBg:function(color){ img.style.backgroundColor = color; } } })(); var proxy = (function(){ var img = document.createElement('img'); img.onload = function(){ delayload.setSrc(img.src); } return { setSrc:function(src){ delayload.setBg("red"); //只需要替换这一句 img.src = src; } } })(); proxy.setSrc("jimmy.jpg"); 使用代理就可以在,最大限度降低代码改动的情况下,完成需求。 var proxy = (function(){ var img = document.createElement('img'); img.onload = function(){ delayload.setSrc(img.src); } return { setSrc:function(src){ //删除~ img.src = src; } } })(); proxy.setSrc("jimmy.jpg"); 仔细观察就可以发现,我接口没改,对象没动,只是将delayload.setBg("red")删除了。 代理的一致性通常来说,代理其实就是本体的一个影子,我有的行为你应该都有,我能sit,代理也能sit. 所以为了不让用于迷惑,这里有一个需求就是,代理的接口名应该和本体的接口名一致,就和上面的setSrc一样. var setImg = (function(){ var img = document.querySelector("#img"); return function(src){ newImg.src = src; } })(); var proxyImg = (function(){ var newImg = document.createElement("img"); newImg.onload = function(){ setImg(newImg.src); } return function(src){ setImg("loading.gif"); newImg.src = "jimmy.jpg"; } }) 但本人推荐上面那种使用接口的形式,这样拓展性比较强,而且易于复用. 保护代理和虚拟代理这其实很好理解,保护代理就是起到保护作用,用来过滤掉一下不必要的请求,将真正需要的递给本体。 //譬如,验证用户名是否唯一 //这里我们应用,保护代理的思想,如果用户名是不合法的,则不会将该请求给本体执行 var checkUser = function(name){ $.ajax({ url:"xxxxx",type:"POST",contentType:"application/json",data:JSON.stringify({ name:name //用户名 }) }) } var proxy = (function(){ var user = document.querySelector("#username"); return function(){ var userName = user.value; var errMsg = detect(userName,["NotEmpty","isUserName"]); //利用策略模式,验证. if(errMsg){ console.log(errMsg); return; } checkUser(userName); } })(); 可以清楚的看到,如果你的用户名格式不正确,这个请求是不会达到本体的。直接回在proxy里面被拦截掉。所以一个很好的代理(保护代理),能让你的请求100%用在刀刃上。 var send = function(article) { return $.ajax({ url: xxx,type: "POST",contentType: "text/plain",data: article }) } var proxy = (function() { var content = document.querySelector('#article'),timer; return function() { var article = content.value; if (timer) { //不覆盖已经发送的请求 return; } timer = setTimeout(function() { send(article) .then(function() { //执行完成再处理 clearTimeout(timer); timer = null; }) },2000); } })(); setTimeout(function(){ proxy(); },2000); //定时发送请求 就算你手速再快,我就只能2s发一次。 但这只是一个比较简单的实例。如果大家感兴趣可以研究一下,作业部落这个编辑器,他这个markdown同步和体验交互式我迄今为止用过应该算最好的一个了吧~ 缓存代理这个应该是应用最多的一个代理方式了,这种方式能够真正解决运算时间问题,网络不畅问题,离线问题。 function fb(num){ if(num<=1){ return 1; } return num*fb(--num) } //缓存代理出场了 var cProxy = (function(){ var cache = {}; return function(num){ if(cache[num]){ console.log(`this is cache ${cache[num]}`); return cache[num]; } return cache[num] = fb(num); } })(); //测试 console.log(cProxy(4)); //24 cProxy(4); //"this is cache 24" 恩,完美。 我们知道阶乘是比较累的一个计算方法,如果某天你的leader需要你计算很多次fb(2000)。用户的电脑也吃不消啊,所以为了体验,缓存代理是你百分百女友,好好珍惜。 //向后台发请求,获取当前页面的数据 // http.getPage(page); var pageProxy = (function(){ var cache = {}; return function(fn){ //fn作为处理页码数据的函数 var pageData = cache[page]; if(pageData){ return fn(pageData); //返回制定页码的数据 } http.getPage(page) //获取制定页码的数据 .then((data)=>{ cache[page] = data; //存放数据 fn(data); }) } })(); 最后再说一句吧,由于代理写起来需要更多的逻辑和代码,如果你的产经没有什么需求的话,不用代理也是行得通的。还有就是,用不用代理和你原来的本体执行的业务逻辑是完全分开的,即,如果后期产经有什么需求,或者你对自己的代码不满意,重构的时候,再添加代理,这种方式也是很推荐的。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |