成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Magix.Cache介紹

3fuyu / 1048人閱讀

摘要:我們簡單測試下彳刂接下來我們要考慮一但緩存資源數(shù)超出了我們規(guī)定的時,我們要清理掉不常用的資源。是一個區(qū)塊管理框架,項目地址在這里區(qū)塊介紹在這里區(qū)塊介紹

轉(zhuǎn)載請注明出處:https://github.com/thx/magix/...

在前端開發(fā)過程中,我們經(jīng)常會在內(nèi)存中緩存一些數(shù)據(jù),其實javascript的緩存比較簡單,只需要聲明一個變量或把一些數(shù)據(jù)掛到某個對象上即可,比如我們要實現(xiàn)一個對所有的ajax請求緩存的方法,簡單實現(xiàn)如下:

var cache={};
var request=function(url,callback){
    if(cache[url]){
        callback(cache[url]);
    }else{
        $.ajax({
            url:url,
            success:function(data){
                callback(cache[url]=data);
            }
        });
    }
};

注意
示例中僅做簡單演示,未考慮同時對相同的url請求多次,比如

request("/a");
request("/a");

在上述代碼中仍然會發(fā)起2次對a的請求,這不是我們討論的重點,我們重點討論請求成功并緩存數(shù)據(jù)后,再請求該url的事情,所以這個問題略過不題

我們回頭看一下我們的request方法,會發(fā)現(xiàn)這樣的問題:

有些url在整個項目中或許只請求一次,我們?nèi)匀粚λ慕Y(jié)果進行緩存,造成資源被白白占用,如果應用在移動端,移動端的內(nèi)存資源本身就比較寶貴,所以我們不能浪費

所以針對request方法中的緩存做一些改進,使它更智能些。我們需要一種算法,保證緩存的個數(shù)不能太多,同時緩存的資源數(shù)超多時,它能聰明的刪掉那些不常用的緩存數(shù)據(jù)

那我們看一下,當我們要實現(xiàn)這樣一個算法有哪些關(guān)鍵點要考慮:

我們需要知道緩存中緩存了多少個資源

當我們從緩存中獲取某個緩存資源時,獲取的算法復雜度應該是o(1),緩存模塊的作用是提高程序的效率,拿空間換時間,所以緩存模塊不應該占用過多的CPU時間

明確目標后,我們就需要尋找合適的對象來緩存我們的數(shù)據(jù):

var obj={}

根據(jù)key從obj上查找某個對象,復雜度是o(1),滿足我們的第2條要求,但obj上緩存了多少個資源需要我們自已維護

var obj=[]

根據(jù)key查找某個對象時,復雜度是o(n),但數(shù)組有l(wèi)ength,可以自動的幫我們維護當前緩存了多少個資源

我們知道數(shù)組是特殊的對象,所以我們可以把數(shù)組當成普通的對象來用。

當我們把一個緩存對象push進數(shù)組時,再根據(jù)緩存對象唯一的key,把它放到這個數(shù)組對象上

所以這時候我們第1版本的代碼可能類似這樣:

var Cache=function(){
    this.$cache=[];
};

Cache.prototype.set=function(key,item){
    var cache=this.$cache;
    var wrap={//包裝一次,方便我們放其它信息,同時利用對象引用傳遞
        key:key,
        item:item
    };
    cache.push(wrap);
    cache["cache_"+key]=wrap;//加上cache_的原因是:防止key是數(shù)字或可轉(zhuǎn)化為數(shù)字的字符串,這樣的話就變成了如 cache["2"] 通過下標訪問數(shù)組里面的元素了。
};

Cache.prototype.get=function(key){
    var res=this.$cache["cache_"+key];
    return res.item;//返回放入的資源
};

使用示例如下:

var c=new Cache();
c.set("/api/userinfo",{
    name:"彳刂"
});

console.log(c.get("/api/userinfo"));

這時候我們就完成了初步要求,知道緩存?zhèn)€數(shù),查找時復雜度是o(1)

不過我們?nèi)匀恍枰悄芤恍┑木彺妫?/p>

知道單個緩存資源的使用頻率

知道單個緩存資源的最后使用時間

緩存中最多能放多少個緩存資源

何時清理緩存資源

我們改造下剛才的代碼:

var Cache=function(max){
    this.$cache=[];
+   this.$max=max | 0 ||20;
};

Cache.prototype.set=function(key,item){
    var cache=this.$cache;
-   var wrap={//包裝一次,方便我們放其它信息,同時利用對象引用傳遞
-        key:key,
-        item:item
-    };
+   key="cache_"+key;
+   var wrap=cache[key];
+   if(!cache.hasOwnProperty(key){
+       wrap={};
+       cache.push(wrap);
+       cache[key]=wrap;
+   }
+   wrap.item=item;
+   wrap.fre=1;//初始使用頻率為1
+   wrap.key=key;
+   wrap.time=new Date().getTime();
};

Cache.prototype.get=function(key){
    var res=this.$cache["cache_"+key];
    if(res){
        res.fre++;//更新使用頻率
        res.time=new Date().getTime();
    }
    return res.item;//返回放入的資源
};

在我們第2版本的代碼中,我們添加了最多緩存資源數(shù)max,同時每個緩存資源加入了使用頻率fre及最后使用時間time,同時我們修改了set方法,考慮了相同key的多次set問題。

我們簡單測試下:

var c=new Cache();
c.set("/api/userinfo",{
    name:"彳刂"
});

console.log(c.$cache[0].fre);//1
console.log(c.get("/api/userinfo"));
console.log(c.$cache[0].fre);//2

接下來我們要考慮一但緩存資源數(shù)超出了我們規(guī)定的max時,我們要清理掉不常用的資源。清理時我們根據(jù)頻率的使用fre標志,fre最小的優(yōu)先清理,同時相同的fre,我們優(yōu)先清理time比較小的,這也是time設(shè)計的意義所在。

所以第3版我們的代碼如下:

var Cache=function(max){
    this.$cache=[];
    this.$max=max | 0 ||20;
};

Cache.prototype.set=function(key,item){
    var cache=this.$cache;
    key="cache_"+key;
    var wrap=cache[key];
    if(!cache.hasOwnProperty(key){
+       if(cache.length>=this.$max){
+           cache.sort(function(a,b){
+               return b.fre==a.fre?b.time-a.time:b.fre-a.fre;
+           });
+           var item=cache.pop();//刪除頻率使用最小,時間最早的1個
+           delete cache[item.key];//
+       }
        wrap={};
        cache.push(wrap);
        cache[key]=wrap;
    }
    wrap.item=item;
    wrap.fre=1;//初始使用頻率為1
    wrap.key=key;
    wrap.time=new Date().getTime();
};

Cache.prototype.get=function(key){
    var res=this.$cache["cache_"+key];
    if(res){
        res.fre++;//更新使用頻率
        res.time=new Date().getTime();
    }
    return res.item;//返回放入的資源
};

+Cache.prototype.has=funciton(key){
+   return this.$cache.hasOwnProperty("cache_"+key);
+};

OK,到這里我們就完成了想要的緩存,我們結(jié)合最開始的request方法來進行實際測試:

var cache=new Cache(2);
var request=function(url,callback){
    if(cache.has(url)){
        callback(cache.get(url);
    }else{
        $.ajax({
            url:url,
            success:function(data){
                cache.set(url,data);
                callback(data);
            }
        });
    }

    })
};

//實際使用(假設(shè)下一個request方法被調(diào)用時,前面request的已經(jīng)完成請求并緩存好了數(shù)據(jù)):
request("/api/item1");
request("/api/item2");
request("/api/item1");//命中緩存
request("/api/item3");//達到上限2,cache對象的內(nèi)部$cache排序一次,刪除/api/item2的緩存
request("/api/item4");//仍然達到上限2,cache對象的內(nèi)部$cache排序一次,刪除/api/item3的緩存

request("/api/item3");//接下來需要多次使用/api/item3,但在請求/api/item4時,它已經(jīng)被刪除了,所以我們需要重新請求。完成請求后,因為上限2依然滿足,所以cache對象內(nèi)部的$cache仍然需要排序一次,刪除/api/item4
request("/api/item3");//命中緩存

根據(jù)上述使用,我們發(fā)現(xiàn),一但達到緩存的上限后,帶來的問題如下:

新的緩存資源進來一個,就需要重新排序一次,性能不好

有可能誤刪除接下來可能頻率使用到的緩存資源

這時候我們就需要尋找突破。類比我們經(jīng)常使用的操作系統(tǒng)的緩存區(qū),我們的緩存是否也可以加入一個緩沖區(qū)呢?當整個緩存列表加上緩沖區(qū)都滿的時候,才清空一次緩存區(qū),不但能解決頻繁排序的問題,也能很好的保留接下來程序中可能頻繁使用到的緩存資源

來,緩存的第4版:

var Cache=function(max,buffer){
    this.$cache=[];
    this.$max=max | 0 ||20;
+   this.$buffer=buffer | 0 ||5;
};

Cache.prototype.set=function(key,item){
    var cache=this.$cache;
    key="cache_"+key;
    var wrap=cache[key];
    if(!cache.hasOwnProperty(key){
-        if(cache.length>=this.$max){
+       if(cache.length>=this.$max+this.$buffer){
            cache.sort(function(a,b){
                return b.fre==a.fre?b.time-a.time:b.fre-a.fre;
            });
-            var item=cache.pop();//刪除頻率使用最小,時間最早的1個
-            delete cache[item.key];//
+           var buffer=this.$buffer;
+           while(buffer--){
+               var item=cache.pop();
+               delete cache[item.key];
+           }
        }
        wrap={};
        cache.push(wrap);
        cache[key]=wrap;
    }
    wrap.item=item;
    wrap.fre=1;//初始使用頻率為1
    wrap.key=key;
    wrap.time=new Date().getTime();
};

Cache.prototype.get=function(key){
    var res=this.$cache["cache_"+key];
    if(res){
        res.fre++;//更新使用頻率
        res.time=new Date().getTime();
    }
    return res.item;//返回放入的資源
};

Cache.prototype.has=funciton(key){
    return this.$cache.hasOwnProperty("cache_"+key);
};

這時候我們再結(jié)合request來測試一下:

var cache=new Cache(2,2);//最大2個,2個緩存區(qū),真實可以緩存4個
var request=function(url,callback){
    if(cache.has(url)){
        callback(cache.get(url);
    }else{
        //$.ajax略
    }
};

request("/api/item1");
request("/api/item2");
request("/api/item3");//放在緩沖區(qū)
request("/api/item4");//放在緩沖區(qū)
request("/api/item5");//排序一次,清除/api/item2 /api/item1
request("/api/item6");//放在緩沖區(qū)
request("/api/item7");//放在緩沖區(qū)

至此我們就完成了比較完善的緩存模塊

當然,后續(xù)我們增加緩存資源的生命期,比如20分鐘后清除,也是較容易的,不在這里詳解。

Magix的Cache模塊比這里稍微再復雜些,不過原理都是一樣的。

Magix是一個區(qū)塊管理框架,項目地址在這里magix

區(qū)塊介紹在這里magix區(qū)塊介紹

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/90823.html

相關(guān)文章

  • Magix.Cache介紹

    摘要:我們簡單測試下彳刂接下來我們要考慮一但緩存資源數(shù)超出了我們規(guī)定的時,我們要清理掉不常用的資源。是一個區(qū)塊管理框架,項目地址在這里區(qū)塊介紹在這里區(qū)塊介紹 轉(zhuǎn)載請注明出處:https://github.com/thx/magix/... 在前端開發(fā)過程中,我們經(jīng)常會在內(nèi)存中緩存一些數(shù)據(jù),其實javascript的緩存比較簡單,只需要聲明一個變量或把一些數(shù)據(jù)掛到某個對象上即可,比如我們要實現(xiàn)...

    CatalpaFlat 評論0 收藏0
  • Magix.Cache介紹

    摘要:我們簡單測試下彳刂接下來我們要考慮一但緩存資源數(shù)超出了我們規(guī)定的時,我們要清理掉不常用的資源。是一個區(qū)塊管理框架,項目地址在這里區(qū)塊介紹在這里區(qū)塊介紹 轉(zhuǎn)載請注明出處:https://github.com/thx/magix/... 在前端開發(fā)過程中,我們經(jīng)常會在內(nèi)存中緩存一些數(shù)據(jù),其實javascript的緩存比較簡單,只需要聲明一個變量或把一些數(shù)據(jù)掛到某個對象上即可,比如我們要實現(xiàn)...

    lemanli 評論0 收藏0
  • Magix.Cache介紹

    摘要:我們簡單測試下彳刂接下來我們要考慮一但緩存資源數(shù)超出了我們規(guī)定的時,我們要清理掉不常用的資源。是一個區(qū)塊管理框架,項目地址在這里區(qū)塊介紹在這里區(qū)塊介紹 轉(zhuǎn)載請注明出處:https://github.com/thx/magix/... 在前端開發(fā)過程中,我們經(jīng)常會在內(nèi)存中緩存一些數(shù)據(jù),其實javascript的緩存比較簡單,只需要聲明一個變量或把一些數(shù)據(jù)掛到某個對象上即可,比如我們要實現(xiàn)...

    zhisheng 評論0 收藏0
  • 在前端如何保護共享對象

    摘要:只要保證在開發(fā)中沒有對共享對象的寫入操作,那么發(fā)布到線上時肯定也沒有寫入操作,這時候這個保護方法就是多余的。 什么是共享對象 被多次使用到的同一個對象即為共享對象 比如我們用標準的es模塊來寫一個導出單位轉(zhuǎn)換的模塊 //converter module export default { cmToIn(){ //convert logic } } 當我們在...

    solocoder 評論0 收藏0
  • 高級前端面試題大匯總(只有試題,沒有答案)

    摘要:面試題來源于網(wǎng)絡,看一下高級前端的面試題,可以知道自己和高級前端的差距。 面試題來源于網(wǎng)絡,看一下高級前端的面試題,可以知道自己和高級前端的差距。有些面試題會重復。 使用過的koa2中間件 koa-body原理 介紹自己寫過的中間件 有沒有涉及到Cluster 介紹pm2 master掛了的話pm2怎么處理 如何和MySQL進行通信 React聲明周期及自己的理解 如何...

    kviccn 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<