摘要:虛擬代理和函數(shù)節(jié)流的思想是一樣的,將用戶對(duì)性能的的傷害降低到最低。虛擬代理上面的保護(hù)代理闡述了怎樣去拒絕請(qǐng)求,而虛擬代理的原則是收集請(qǐng)求來者不拒他的出發(fā)點(diǎn)和保護(hù)代理的是一樣的,都是為了節(jié)省請(qǐng)求的開支。
What"s the proxy pattern?
代理模式其實(shí)就是將違反單一性原則的類給抽離出來,盡量滿足開放和封閉的原則。 相當(dāng)于一個(gè)類的行為只是一種,但是你可以給這個(gè)類添加額外的行為。比如: 一個(gè)工廠制造傘,你可以給這個(gè)工廠設(shè)置一個(gè)代理,提供訂單,運(yùn)貨,淘寶網(wǎng)店等多種行為。當(dāng)然,里面還有最關(guān)鍵的一點(diǎn)就是,這個(gè)代理能把一些騙紙和忽悠都過濾掉,將最真實(shí)最直接的訂單給工廠,讓工廠能夠放心的讓工人加班,順利的發(fā)年終獎(jiǎng).
!!!說人話:
就是將你的本體請(qǐng)求,放在代理的懷抱里,讓他來幫你擋風(fēng)擋雨。
圖片延遲加載是指,圖片的加載應(yīng)該在頁面全部加載完后,再去加載。這樣能夠提高加載的速度和網(wǎng)頁的體驗(yàn)性。實(shí)際操作就是,將原來網(wǎng)頁的src獨(dú)立出來,將原來圖片使用一個(gè)loading.gif代替,然后再js里面手動(dòng)創(chuàng)建個(gè)img去加載這個(gè)src,當(dāng)加載完后把src替換就可以了。
沒有使用加載時(shí)
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");
這樣寫,我給滿分(在沒有產(chǎn)經(jīng)這個(gè)生物的前提下).
現(xiàn)在,假設(shè)有一個(gè)初級(jí)產(chǎn)經(jīng)(還沒有進(jìn)化那種)
她有一個(gè)需求: 我不要你的這個(gè)loading.gif圖片,你換一個(gè)。
恩,好沒問題。 (不過就是換一下src而已)
她又有一個(gè)需求: 你這loading.gif好丑,你弄一個(gè)純色的.
MD~ 搞什么,你這樣我很為難誒,我邏輯都變了,你讓我這個(gè)改。。
所以,為了應(yīng)對(duì)產(chǎn)經(jīng)這個(gè)神奇的物種,推薦使用代理模式這個(gè)岡本,去降服產(chǎn)經(jīng).
來,上岡本
//將背景圖設(shè)置,和圖片加載的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");
恩,如果產(chǎn)經(jīng)要求換圖片,好解決,換一下loading.gif就over了.如果產(chǎn)經(jīng)要求換成純色的。也行。 再加一個(gè)方法.
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");
使用代理就可以在,最大限度降低代碼改動(dòng)的情況下,完成需求。
當(dāng)然,
如果有一天神奇生物又提出一個(gè)需求:
親,我們現(xiàn)在寬帶升級(jí)了,有100M了誒,你可以把加載去掉了吧,直接讓用戶一下就用看見圖片了哦。
(呵呵~我丟你雷姆)
沒事,誰叫我有代理模式(岡本)嘞。改~
神奇的事發(fā)生了.
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");
仔細(xì)觀察就可以發(fā)現(xiàn),我接口沒改,對(duì)象沒動(dòng),只是將delayload.setBg("red")刪除了。
加載功能還在,只是我使用代理傳了一層。66666
通常來說,代理其實(shí)就是本體的一個(gè)影子,我有的行為你應(yīng)該都有,我能sit,代理也能sit. 所以為了不讓用于迷惑,這里有一個(gè)需求就是,代理的接口名應(yīng)該和本體的接口名一致,就和上面的setSrc一樣.
但通常這是個(gè)主要是針對(duì)java的靜態(tài)語言的要求。因?yàn)樵趈s里面沒有實(shí)現(xiàn)接口的繼承,而且在js里面,函數(shù)是名副其實(shí)的一等公民,所以這里對(duì)于代理的一直性要求就沒有這么高了。
上面其實(shí)可以改寫為:
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"; } })
但本人推薦上面那種使用接口的形式,這樣拓展性比較強(qiáng),而且易于復(fù)用.
保護(hù)代理和虛擬代理這其實(shí)很好理解,保護(hù)代理就是起到保護(hù)作用,用來過濾掉一下不必要的請(qǐng)求,將真正需要的遞給本體。
虛擬代理和函數(shù)節(jié)流的思想是一樣的,將用戶對(duì)性能的rape的傷害降低到最低。就像送快遞一樣,一件一件的送,這個(gè)公司是不是傻~ 所以為了生存,快遞公司會(huì)當(dāng)物品積攢到一定程度后才會(huì)讓快遞哥騎著小電驢穿梭在神州大地上。
保護(hù)代理
//譬如,驗(yàn)證用戶名是否唯一 //這里我們應(yīng)用,保護(hù)代理的思想,如果用戶名是不合法的,則不會(huì)將該請(qǐng)求給本體執(zhí)行 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"]); //利用策略模式,驗(yàn)證. if(errMsg){ console.log(errMsg); return; } checkUser(userName); } })();
可以清楚的看到,如果你的用戶名格式不正確,這個(gè)請(qǐng)求是不會(huì)達(dá)到本體的。直接回在proxy里面被攔截掉。所以一個(gè)很好的代理(保護(hù)代理),能讓你的請(qǐng)求100%用在刀刃上。
虛擬代理
上面的保護(hù)代理闡述了怎樣去拒絕請(qǐng)求,而虛擬代理的原則是收集請(qǐng)求(來者不拒). 他的出發(fā)點(diǎn)和保護(hù)代理的是一樣的,都是為了節(jié)省請(qǐng)求的開支。
比如: 一個(gè)在線的編輯器,他是怎樣同步你的內(nèi)容呢?不會(huì)是,你內(nèi)容一改變就發(fā)送一起請(qǐng)求同步吧。這個(gè)想法顯然不切實(shí)際。如果這樣,我每天沒事都會(huì)打開這個(gè)編輯器,把a(bǔ)sfdsafdsafsad...在里面敲上幾分鐘。保證分分鐘弄死他的服務(wù)器。所以一般,我們會(huì)使用虛擬代理來接受你的請(qǐng)求。
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) { //不覆蓋已經(jīng)發(fā)送的請(qǐng)求 return; } timer = setTimeout(function() { send(article) .then(function() { //執(zhí)行完成再處理 clearTimeout(timer); timer = null; }) }, 2000); } })(); setTimeout(function(){ proxy(); },2000); //定時(shí)發(fā)送請(qǐng)求
就算你手速再快,我就只能2s發(fā)一次。 但這只是一個(gè)比較簡(jiǎn)單的實(shí)例。如果大家感興趣可以研究一下,作業(yè)部落這個(gè)編輯器,他這個(gè)markdown同步和體驗(yàn)交互式我迄今為止用過應(yīng)該算最好的一個(gè)了吧~
緩存代理這個(gè)應(yīng)該是應(yīng)用最多的一個(gè)代理方式了,這種方式能夠真正解決運(yùn)算時(shí)間問題,網(wǎng)絡(luò)不暢問題,離線問題。
搬一個(gè)例子過來吧。
計(jì)算乘積問題
function fb(num){ if(num<=1){ return 1; } return num*fb(--num) } //緩存代理出場(chǎng)了 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); } })(); //測(cè)試 console.log(cProxy(4)); //24 cProxy(4); //"this is cache 24"
恩,完美。 我們知道階乘是比較累的一個(gè)計(jì)算方法,如果某天你的leader需要你計(jì)算很多次fb(2000)。用戶的電腦也吃不消啊,所以為了體驗(yàn),緩存代理是你百分百女友,好好珍惜。
當(dāng)然,緩存代理并不只有這一點(diǎn)用途,比如需要重復(fù)獲取網(wǎng)頁中大部分?jǐn)?shù)據(jù)的時(shí)候,就可以考慮使用緩存代理。前端工作者,99.9999%的應(yīng)該都會(huì)遇見分頁的問題(請(qǐng)不要告訴我你的分頁是同步方式). 當(dāng)我們點(diǎn)擊一個(gè)頁面的時(shí)候,獲取后臺(tái)的數(shù)據(jù),然后再由我恩渲染到頁面上,這是這樣一個(gè)流程。 首先,渲染流程可以復(fù)用,那數(shù)據(jù)的復(fù)用性該怎么做呢?
恩,猜到了吧,就是使用cache進(jìn)行一個(gè)緩存,然后如果下次獲取分頁的頁碼一致的話,就可以直接使用該數(shù)據(jù)了。
//向后臺(tái)發(fā)請(qǐng)求,獲取當(dāng)前頁面的數(shù)據(jù) // http.getPage(page); var pageProxy = (function(){ var cache = {}; return function(fn){ //fn作為處理頁碼數(shù)據(jù)的函數(shù) var pageData = cache[page]; if(pageData){ return fn(pageData); //返回制定頁碼的數(shù)據(jù) } http.getPage(page) //獲取制定頁碼的數(shù)據(jù) .then((data)=>{ cache[page] = data; //存放數(shù)據(jù) fn(data); }) } })();
最后再說一句吧,由于代理寫起來需要更多的邏輯和代碼,如果你的產(chǎn)經(jīng)沒有什么需求的話,不用代理也是行得通的。還有就是,用不用代理和你原來的本體執(zhí)行的業(yè)務(wù)邏輯是完全分開的,即,如果后期產(chǎn)經(jīng)有什么需求,或者你對(duì)自己的代碼不滿意,重構(gòu)的時(shí)候,再添加代理,這種方式也是很推薦的。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/78492.html
摘要:因此,另一種解決辦法像這樣的工具,則只是將和進(jìn)行了結(jié)合,其功能尤其關(guān)注日志管理,比如格式檢查,日志語法分析,數(shù)據(jù)改進(jìn)地址地理位置信息,元數(shù)據(jù)標(biāo)簽等以及日志路由。 由Rancher社區(qū)維護(hù)的應(yīng)用商店最近迎來了兩個(gè)明星項(xiàng)目——SPM 和 Logsene,來自Sematext的監(jiān)控與日志工具。如果你已經(jīng)熟悉Logstash,Kibana,Prometheus,Grafana這些監(jiān)控或日志解決...
摘要:內(nèi)置了三種發(fā)送網(wǎng)絡(luò)請(qǐng)求的方式和。轉(zhuǎn)換二進(jìn)制為發(fā)送到目前為止,不能發(fā)送非序列化的數(shù)據(jù),所以,要發(fā)送二進(jìn)制數(shù)據(jù),采用編碼的字符串是個(gè)不錯(cuò)的選擇。在最新版本的層也已經(jīng)支持協(xié)議來傳輸二進(jìn)制文件,但是,相應(yīng)的原生平臺(tái)的網(wǎng)絡(luò)模塊暫時(shí)還不支持。 端) 本文原創(chuàng),轉(zhuǎn)載請(qǐng)注明作者及出處 在使用React Native開發(fā)中,我們熟練的采用JavaScript的方式發(fā)送請(qǐng)求的方式發(fā)送一個(gè)請(qǐng)求到服務(wù)端,但是...
摘要:引用計(jì)數(shù)這是最簡(jiǎn)單的垃圾收集算法。然而,引用計(jì)數(shù)算法考慮到它們互相都有至少一次引用,所以它們不會(huì)被回收。事件代理發(fā)生在冒泡階段。為時(shí)取消事件默認(rèn)行為,為時(shí)取消時(shí)間傳播通常利用事件冒泡機(jī)制托管事件處理程序提高程序性能。 JS延遲加載的方式有哪些? JS的延遲加載有助與提高頁面的加載速度。defer和async、動(dòng)態(tài)創(chuàng)建DOM方式(用得最多)、按需異步載入JSdefer:延遲腳本。立即下載...
閱讀 2748·2021-11-18 10:02
閱讀 3479·2021-09-28 09:35
閱讀 2720·2021-09-22 15:12
閱讀 813·2021-09-22 15:08
閱讀 3362·2021-09-07 09:58
閱讀 3533·2021-08-23 09:42
閱讀 793·2019-08-30 12:53
閱讀 2149·2019-08-29 13:51