摘要:只要保證在開發(fā)中沒有對共享對象的寫入操作,那么發(fā)布到線上時肯定也沒有寫入操作,這時候這個保護方法就是多余的。
什么是共享對象
被多次使用到的同一個對象即為共享對象
比如我們用標準的es模塊來寫一個導(dǎo)出單位轉(zhuǎn)換的模塊
//converter module export default { cmToIn(){ //convert logic } }
當我們在其它模塊中使用該模塊時,converter即是共享對象,內(nèi)存中只有一份,不管它被import了多少次。
同理,上面展示的是通用方法的對象集合,在前端項目里,我們也會把一些所謂寫死的數(shù)據(jù)集中封裝在某個模塊里,方便后期的修改,比如我們實現(xiàn)一個constant常量模塊,我們把一些項目中使用的,后期可能會修改的數(shù)據(jù)放進去
//constant export default { dateFormatter:"YYYY-MM-DD", reports:{ productId:"123", productName:"456" } }
這里僅示意一下
為什么要保護共享對象防止共享的對象被意外修改導(dǎo)致線上故障
原則上這些通用的模塊,我們不會,也不會有意的在我們業(yè)務(wù)代碼中去修改里面的數(shù)據(jù),尤其像常量這樣的模塊,如果要修改的話,我們肯定修改常量這個模塊。
但是,凡事總有意外,比如說我們有這樣一個場景:根據(jù)后端返回的用信息,以及前端寫死的一些常量,來判斷某個用戶能不能展示某個報表,我們期望的代碼可能是這樣的
import Constant from "./constant";//引入我們前面定義的constant模塊 //...其它略 export default View.extend({ render(){ //...其它邏輯略 if(Constant.reports.productId==user.reportProductId){ //.... } } });
注意上述代碼中的if語句,如果錯寫成:if(Constant.reports.productId=user.reportProductId),兩個等號的比較寫成了一個等號的賦值。
如果自測的時候,用戶接口里user.reportProductId返回的正好也是123,那么先賦值,再做if判斷,成立,做為開發(fā)者會錯誤的以為這里的邏輯沒問題。當然,正常情況下也要測試下用戶接口里user.reportProductId返回不是123的情況,這時候或許就能發(fā)現(xiàn)問題。
如果上述問題沒有測試出來,陰差陽錯的上線之后,這個問題對于大型單頁應(yīng)用是致命的,如果某個用戶的reportProductId是456,訪問了寫錯的頁面后,因為被意外的修改了constant中的reports.productId,會導(dǎo)致后續(xù)其它模塊在讀取時不再是最初的123而出問題
如何保護共享對象 constconst關(guān)鍵字聲明的僅防止變量被重新賦值,無法防止對象修改Object.freeze
可以防止被修改,但是如果對象嵌套時,被嵌套的對象依然可以被修改,需要開發(fā)者對要freeze的對象遞歸遍歷進行freeze。最重要的一點是,當我修改一個freeze對象時,雖然修改不成功,但也沒有任務(wù)失敗的提示,在前述場景中,我們還是希望開發(fā)者在修改一個不允許的被修改的對象時能及時給出相應(yīng)的提示。Proxy
es6新增的代理操作對象的方法
Proxy相關(guān)的文章非常多,這里就不再詳細說,我們借助Proxy來實現(xiàn)一個Safeguard方法來保護我們的共享對象
const Safeguard = o => { let build = o => { let entity = new Proxy(o, { set() { throw new Error("readonly"); }, get(target, property) { let out = target[property]; if (target.hasOwnProperty(property) && (Array.isArray(out) || Object.prototype.toString.call(out) == "[object Object]")) { return build(out); } return out; } }); return entity; }; return build(o); }
這里簡化了代碼,你可以根據(jù)自己的需要去調(diào)整相應(yīng)的實現(xiàn)邏輯
使用
const user=Safeguard({ name:"行列", address:{ city:"hz" } });
這個user對象只能讀,不能寫,當開發(fā)者嘗試寫入新數(shù)據(jù)時,會拋出錯誤提示開發(fā)者
使用場景 地址欄解析對象在單頁應(yīng)用中,我們需要把地址欄中的字符串地址解析成對象,方便我們使用。
比如/path/name?a=b&c=d,我們可能解析成這樣的對象
{ path:"/path/name", params:{ a:"b", c:"d" } }
如果你統(tǒng)計過你的單頁應(yīng)用,會發(fā)現(xiàn)固定的用戶總是只訪問某些頁面,我們可以在用戶訪問某個頁面時,臨時的把地址欄中的這個地址字符串解析一遍,也可以把解析結(jié)果存起來,當用戶再訪問這個頁面時,不需要解析,把存起來的結(jié)果拿出來使用即可
關(guān)于這一塊我曾經(jīng)寫過Magix.Cache,詳細的來說明該如何智能的緩存哪些需要的信息
對于緩存后的地址欄信息對象,它就是一個共享對象,要確保它不能被開發(fā)者寫入新的值,就可以使用前面我們定義的Safeguard方法來進行保護
緩存的接口數(shù)據(jù)在單頁應(yīng)用開發(fā)中,有些數(shù)據(jù)需要后端提供,但是后端提供的這些數(shù)據(jù)可能在很長一段時間內(nèi)都不會被修改,比如省市數(shù)據(jù),前端沒必要在每次需要使用這種數(shù)據(jù)時都請求一次,所以前端可以把該接口的數(shù)據(jù)緩存下來,來節(jié)省請求
對于這樣的數(shù)據(jù)對象,也需要保護,簡言之,只要是共用的對象,均需要防止它被意外的修改
關(guān)于上線前面我們聊到的Safeguard方法,在我看來是沒必要發(fā)布到線上的,只要開發(fā)階段存在即可。只要保證在開發(fā)中沒有對共享對象的寫入操作,那么發(fā)布到線上時肯定也沒有寫入操作,這時候這個保護Safeguard方法就是多余的。
如何在開發(fā)時保護,而發(fā)布到線上時去掉呢?
我們可以使用uglify這個代碼壓縮工具的global_defs配置。比如在開發(fā)階段這樣定義
if (typeof DEBUG == "undefined") window.DEBUG = true; //... const user={ name:"行列", address:{ city:"hz" } } if(DEBUG){ user=Safeguard(user); }
然后在壓縮時:
uglify({ compress: { global_defs: { DEBUG: false } }, output: { ascii_only: true } });
那么這樣壓縮出來的代碼就不包含DEBUG相關(guān)的語句了
當然,Safeguard跟隨上線也沒有什么大問題,最后這個“關(guān)于上線”這塊只是想做更深入的探討,如果Safeguard要上到線上,注意Proxy的兼容即可
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/97350.html
摘要:并發(fā)模塊本身有兩種不同的類型進程和線程,兩個基本的執(zhí)行單元。調(diào)用以啟動新線程。在大多數(shù)系統(tǒng)中,時間片發(fā)生不可預(yù)知的和非確定性的,這意味著線程可能隨時暫停或恢復(fù)。 大綱 什么是并發(fā)編程?進程,線程和時間片交織和競爭條件線程安全 策略1:監(jiān)禁 策略2:不可變性 策略3:使用線程安全數(shù)據(jù)類型 策略4:鎖定和同步 如何做安全論證總結(jié) 什么是并發(fā)編程? 并發(fā)并發(fā)性:多個計算同時發(fā)生。 在現(xiàn)代...
摘要:我們知道在并發(fā)編程中,不能使用多把鎖保護同一個資源,因為這樣達不到線程互斥的效果,存在線程安全的問題。兩個線程都完成轉(zhuǎn)賬操作后,的賬戶余額可能為,也可能為,但是不可能為。摘要:在編寫多線程并發(fā)程序時,我明明對共享資源加鎖了啊?為什么還是出問題呢?問題到底出在哪里呢?其實,我想說的是:你的加鎖姿勢正確嗎?本文分享自華為云社區(qū)《【高并發(fā)】高并發(fā)環(huán)境下詭異的加鎖問題(你加的鎖未必安全)》,作者:冰...
摘要:同一時刻只有一個線程執(zhí)行這個條件非常重要,我們稱之為互斥。那對于像轉(zhuǎn)賬這種有關(guān)聯(lián)關(guān)系的操作,我們應(yīng)該怎么去解決呢先把這個問題代碼化。 在前面的分享中我們提到。 一個或者多個操作在 CPU 執(zhí)行的過程中不被中斷的特性,稱為原子性 思考:在32位的機器上對long型變量進行加減操作存在并發(fā)問題,什么原因!? 原子性問題如何解決 我們已經(jīng)知道原子性問題是線程切換,而操作系統(tǒng)做線程切換是依賴 ...
摘要:有的情況下我們希望自己設(shè)計的類可以讓客戶端程序員們不需要使用額外的同步操作就可以放心的在多線程環(huán)境下使用,我們就把這種類成為線程安全類。 設(shè)計線程安全的類 前邊我們對線程安全性的分析都停留在一兩個可變共享變量的基礎(chǔ)上,真實并發(fā)程序中可變共享變量會非常多,在出現(xiàn)安全性問題的時候很難準確定位是哪塊兒出了問題,而且修復(fù)問題的難度也會隨著程序規(guī)模的擴大而提升(因為在程序的各個位置都可以隨便使用...
摘要:題記三國時赤壁鏖戰(zhàn),孔明說,天有不測風(fēng)云,欲破曹公,宜用火攻,萬事俱備,只欠東風(fēng)。現(xiàn)在公共云混戰(zhàn),我想說,無災(zāi)備不上云,保護數(shù)據(jù),未雨綢繆,帶了雨傘,還需雨衣。題記:三國時赤壁鏖戰(zhàn),孔明說,天有不測風(fēng)云,欲破曹公,宜用火攻,萬事俱備,只欠東風(fēng)。現(xiàn)在公共云混戰(zhàn),我想說,無災(zāi)備不上云,保護數(shù)據(jù),未雨綢繆,帶了雨傘,還需雨衣。未雨綢繆,到底是帶雨傘還是雨衣呢?時代在變,人的追求也在變。隨著公共云對...
閱讀 2485·2021-11-24 09:39
閱讀 3528·2019-08-30 15:53
閱讀 602·2019-08-29 15:15
閱讀 2909·2019-08-26 13:23
閱讀 3224·2019-08-26 10:48
閱讀 650·2019-08-26 10:31
閱讀 776·2019-08-26 10:30
閱讀 2370·2019-08-23 18:32