<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      imagepool前端圖片加載管理器(JavaScript圖片連接池)

      前言

       

            imagepool是一款管理圖片加載的JS工具,通過imagepool可以控制圖片并發(fā)加載個數(shù)。

            對于圖片加載,最原始的方式就是直接寫個img標簽,比如:<img src="圖片url" />

            經(jīng)過不斷優(yōu)化,出現(xiàn)了圖片延遲加載方案,這回圖片的URL不直接寫在src屬性中,而是寫在某個屬性中,比如:<img src="" data-src="圖片url" />。這樣瀏覽器就不會自動加載圖片,等到一個恰當?shù)臅r機需要加載了,則用js把data-src屬性中的url放到img標簽的src屬性中,或者讀出url后,用js去加載圖片,加載完成后再設(shè)置src屬性,顯示出圖片。

            這看起來已經(jīng)控制的很好了,但依然會有問題。

            雖然能做到只加載一部分圖片,但這一部分圖片,仍然可能是一個比較大的數(shù)量級。

            這對于PC端來說,沒什么大不了,但對于移動端,圖片并發(fā)加載數(shù)量過多,極有可能引起應(yīng)用崩潰。

            因此我們迫切需要一種圖片緩沖機制,來控制圖片加載并發(fā)。類似于后端的數(shù)據(jù)庫連接池,既不會創(chuàng)建過多連接,又能充分復(fù)用每一個連接。

            至此,imagepool誕生了。

       

       拙劣的原理圖

       

       

      使用說明

       

           首先要初始化連接池:

      1 var imagepool = initImagePool(5);

           initImagePool 是全局方法,任何地方都可以直接使用。作用是創(chuàng)建一個連接池,并且可以指定連接池的最大連接數(shù),可選,默認為5。

           在同一個頁面中,多次調(diào)用initImagePool均返回同一個核心實例,永遠是第一個,有點單例的感覺。比如:

      1 var imagepool1 = initImagePool(3);
      2 var imagepool2 = initImagePool(7);

           此時imagepool1和imagepool2的最大連接數(shù)均為3,內(nèi)部使用的是同一個核心實例。注意,是內(nèi)部的核心相同,并不是說imagepool1 === imagepool2。

           初始化之后,就可以放心大膽的加載圖片了。

           最簡單的調(diào)用方法如下:

       1 var imagepool = initImagePool(10);
       2 
       3 imagepool.load("圖片url",{
       4     success: function(src){
       5         console.log("success:::::"+src);
       6     },
       7     error: function(src){
       8         console.log("error:::::"+src);
       9     }
      10 });

           直接在實例上調(diào)用load方法即可。

           load方法有兩個參數(shù)。第一個參數(shù)是需要加載的圖片url,第二個參數(shù)是各種選項,包含了成功、失敗的回調(diào),回調(diào)時會傳入圖片url。

           這樣寫只能傳入一張圖片,因此,也可以寫成如下形式:

       1 var imagepool = initImagePool(10);
       2 
       3 imagepool.load(["圖片1url","圖片2url"],{
       4     success: function(src){
       5         console.log("success:::::"+src);
       6     },
       7     error: function(src){
       8         console.log("error:::::"+src);
       9     }
      10 });

           通過傳入一個圖片url數(shù)組,就可以傳入多個圖片了。

           每一個圖片加載成功(或失敗),都會調(diào)用success(或error)方法,并且傳入對應(yīng)的圖片url。

           但有時候我們并不需要這樣頻繁的回調(diào),傳入一個圖片url數(shù)組,當這個數(shù)組中所有的圖片都處理完成后,再回調(diào)就可以了。

           只需加一個選項即可:

       1 var imagepool = initImagePool(10);
       2 
       3 imagepool.load(["圖片1url ","圖片2url "],{
       4     success: function(sArray, eArray, count){
       5         console.log("sArray:::::"+sArray);
       6         console.log("eArray:::::"+eArray);
       7         console.log("count:::::"+count);
       8     },
       9     error: function(src){
      10         console.log("error:::::"+src);
      11     },
      12     once: true
      13 });

           通過在選項中加一個once屬性,并設(shè)置為true,即可實現(xiàn)只回調(diào)一次。

           這一次回調(diào),必然回調(diào)success方法,此時error方法是被忽略的。

           此時回調(diào)success方法,不再是傳入一個圖片url參數(shù),而是傳入三個參數(shù),分別為:成功的url數(shù)組、失敗的url數(shù)組、總共處理的圖片個數(shù)。

           此外,還有一個方法可以獲取連接池內(nèi)部狀態(tài):

      1 var imagepool = initImagePool(10);
      2 
      3 console.log(imagepool.info());

           通過調(diào)用info方法,可以得到當前時刻連接池內(nèi)部狀態(tài),數(shù)據(jù)結(jié)構(gòu)如下:

       

      •      Object.task.count 連接池中等待處理的任務(wù)數(shù)量
      •      Object.thread.count 連接池最大連接數(shù)
      •      Object.thread.free 連接池空閑連接數(shù)

       

           建議不要頻繁調(diào)用此方法。

       

           最后需要說明的是,如果圖片加載失敗,最多會嘗試3次,如果最后還是加載失敗,才回調(diào)error方法。嘗試次數(shù)可在源碼中修改。

           最最后再強調(diào)一下,讀者可以盡情的往連接池中push圖片,完全不必擔心并發(fā)過多的問題,imagepool會有條不絮的幫你加載這些圖片。

           最最最后,必須說明的是,imagepool理論上不會降低圖片加載速度,只不過是平緩的加載。

       

      源碼

       

        1 (function(exports){
        2     //單例
        3     var instance = null;
        4     var emptyFn = function(){};
        5 
        6     //初始默認配置
        7     var config_default = {
        8         //線程池"線程"數(shù)量
        9         thread: 5,
       10         //圖片加載失敗重試次數(shù)
       11         //重試2次,加上原有的一次,總共是3次
       12         "try": 2
       13     };
       14 
       15     //工具
       16     var _helpers = {
       17         //設(shè)置dom屬性
       18         setAttr: (function(){
       19             var img = new Image();
       20             //判斷瀏覽器是否支持HTML5 dataset
       21             if(img.dataset){
       22                 return function(dom, name, value){
       23                     dom.dataset[name] = value;
       24                     return value;
       25                 };
       26             }else{
       27                 return function(dom, name, value){
       28                     dom.setAttribute("data-"+name, value);
       29                     return value;
       30                 };
       31             }
       32         }()),
       33         //獲取dom屬性
       34         getAttr: (function(){
       35             var img = new Image();
       36             //判斷瀏覽器是否支持HTML5 dataset
       37             if(img.dataset){
       38                 return function(dom, name){
       39                     return dom.dataset[name];
       40                 };
       41             }else{
       42                 return function(dom, name){
       43                     return dom.getAttribute("data-"+name);
       44                 };
       45             }
       46         }())
       47     };
       48 
       49     /**
       50      * 構(gòu)造方法
       51      * @param max 最大連接數(shù)。數(shù)值。
       52      */
       53     function ImagePool(max){
       54         //最大并發(fā)數(shù)量
       55         this.max = max || config_default.thread;
       56         this.linkHead = null;
       57         this.linkNode = null;
       58         //加載池
       59         //[{img: dom,free: true, node: node}]
       60         //node
       61         //{src: "", options: {success: "fn",error: "fn", once: true}, try: 0}
       62         this.pool = [];
       63     }
       64 
       65     /**
       66      * 初始化
       67      */
       68     ImagePool.prototype.initPool = function(){
       69         var i,img,obj,_s;
       70 
       71         _s = this;
       72         for(i = 0;i < this.max; i++){
       73             obj = {};
       74             img = new Image();
       75             _helpers.setAttr(img, "id", i);
       76             img.onload = function(){
       77                 var id,src;
       78                 //回調(diào)
       79                 //_s.getNode(this).options.success.call(null, this.src);
       80                 _s.notice(_s.getNode(this), "success", this.src);
       81 
       82                 //處理任務(wù)
       83                 _s.executeLink(this);
       84             };
       85             img.onerror = function(e){
       86                 var node = _s.getNode(this);
       87 
       88                 //判斷嘗試次數(shù)
       89                 if(node.try < config_default.try){
       90                     node.try = node.try + 1;
       91                     //再次追加到任務(wù)鏈表末尾
       92                     _s.appendNode(_s.createNode(node.src, node.options, node.notice, node.group, node.try));
       93 
       94                 }else{
       95                     //error回調(diào)
       96                     //node.options.error.call(null, this.src);
       97                     _s.notice(node, "error", this.src);
       98                 }
       99 
      100                 //處理任務(wù)
      101                 _s.executeLink(this);
      102             };
      103             obj.img = img;
      104             obj.free = true;
      105             this.pool.push(obj);
      106         }
      107     };
      108 
      109     /**
      110      * 回調(diào)封裝
      111      * @param node 節(jié)點。對象。
      112      * @param status 狀態(tài)。字符串。可選值:success(成功)|error(失敗)
      113      * @param src 圖片路徑。字符串。
      114      */
      115     ImagePool.prototype.notice = function(node, status, src){
      116         node.notice(status, src);
      117     };
      118 
      119     /**
      120      * 處理鏈表任務(wù)
      121      * @param dom 圖像dom對象。對象。
      122      */
      123     ImagePool.prototype.executeLink = function(dom){
      124         //判斷鏈表是否存在節(jié)點
      125         if(this.linkHead){
      126             //加載下一個圖片
      127             this.setSrc(dom, this.linkHead);
      128             //去除鏈表頭
      129             this.shiftNode();
      130         }else{
      131             //設(shè)置自身狀態(tài)為空閑
      132             this.status(dom, true);
      133         }
      134     };
      135 
      136     /**
      137      * 獲取空閑"線程"
      138      */
      139     ImagePool.prototype.getFree = function(){
      140         var length,i;
      141         for(i = 0, length = this.pool.length; i < length; i++){
      142             if(this.pool[i].free){
      143                 return this.pool[i];
      144             }
      145         }
      146 
      147         return null;
      148     };
      149 
      150     /**
      151      * 封裝src屬性設(shè)置
      152      * 因為改變src屬性相當于加載圖片,所以把操作封裝起來
      153      * @param dom 圖像dom對象。對象。
      154      * @param node 節(jié)點。對象。
      155      */
      156     ImagePool.prototype.setSrc = function(dom, node){
      157         //設(shè)置池中的"線程"為非空閑狀態(tài)
      158         this.status(dom, false);
      159         //關(guān)聯(lián)節(jié)點
      160         this.setNode(dom, node);
      161         //加載圖片
      162         dom.src = node.src;
      163     };
      164 
      165     /**
      166      * 更新池中的"線程"狀態(tài)
      167      * @param dom 圖像dom對象。對象。
      168      * @param status 狀態(tài)。布爾。可選值:true(空閑)|false(非空閑)
      169      */
      170     ImagePool.prototype.status = function(dom, status){
      171         var id = _helpers.getAttr(dom, "id");
      172         this.pool[id].free = status;
      173         //空閑狀態(tài),清除關(guān)聯(lián)的節(jié)點
      174         if(status){
      175             this.pool[id].node = null;
      176         }
      177     };
      178 
      179     /**
      180      * 更新池中的"線程"的關(guān)聯(lián)節(jié)點
      181      * @param dom 圖像dom對象。對象。
      182      * @param node 節(jié)點。對象。
      183      */
      184     ImagePool.prototype.setNode = function(dom, node){
      185         var id = _helpers.getAttr(dom, "id");
      186         this.pool[id].node = node;
      187         return this.pool[id].node === node;
      188     };
      189 
      190     /**
      191      * 獲取池中的"線程"的關(guān)聯(lián)節(jié)點
      192      * @param dom 圖像dom對象。對象。
      193      */
      194     ImagePool.prototype.getNode = function(dom){
      195         var id = _helpers.getAttr(dom, "id");
      196         return this.pool[id].node;
      197     };
      198 
      199     /**
      200      * 對外接口,加載圖片
      201      * @param src 可以是src字符串,也可以是src字符串數(shù)組。
      202      * @param options 用戶自定義參數(shù)。包含:success回調(diào)、error回調(diào)、once標識。
      203      */
      204     ImagePool.prototype.load = function(src, options){
      205         var srcs = [],
      206             free = null,
      207             length = 0,
      208             i = 0,
      209             //只初始化一次回調(diào)策略
      210             notice = (function(){
      211                 if(options.once){
      212                     return function(status, src){
      213                         var g = this.group,
      214                             o = this.options;
      215 
      216                         //記錄
      217                         g[status].push(src);
      218                         //判斷改組是否全部處理完成
      219                         if(g.success.length + g.error.length === g.count){
      220                             //異步
      221                             //實際上是作為另一個任務(wù)單獨執(zhí)行,防止回調(diào)函數(shù)執(zhí)行時間過長影響圖片加載速度
      222                             setTimeout(function(){
      223                                 o.success.call(null, g.success, g.error, g.count);
      224                             },1);
      225                         }
      226                     };
      227                 }else{
      228                     return function(status, src){
      229                         var o = this.options;
      230 
      231                         //直接回調(diào)
      232                         setTimeout(function(){
      233                             o[status].call(null, src);
      234                         },1);
      235                     };
      236                 }
      237             }()),
      238             group = {
      239                 count: 0,
      240                 success: [],
      241                 error: []
      242             },
      243             node = null;
      244         options = options || {};
      245         options.success = options.success || emptyFn;
      246         options.error = options.error || emptyFn;
      247         srcs = srcs.concat(src);
      248 
      249         //設(shè)置組元素個數(shù)
      250         group.count = srcs.length;
      251         //遍歷需要加載的圖片
      252         for(i = 0, length = srcs.length; i < length; i++){
      253             //創(chuàng)建節(jié)點
      254             node = this.createNode(srcs[i], options, notice, group);
      255             //判斷線程池是否有空閑
      256             free = this.getFree();
      257             if(free){
      258                 //有空閑,則立即加載圖片
      259                 this.setSrc(free.img, node);
      260             }else{
      261                 //沒有空閑,將任務(wù)添加到鏈表
      262                 this.appendNode(node);
      263             }
      264         }
      265     };
      266 
      267     /**
      268      * 獲取內(nèi)部狀態(tài)信息
      269      * @returns {{}}
      270      */
      271     ImagePool.prototype.info = function(){
      272         var info = {},
      273             length = 0,
      274             i = 0,
      275             node = null;
      276         //線程
      277         info.thread = {};
      278         //線程總數(shù)量
      279         info.thread.count = this.pool.length;
      280         //空閑線程數(shù)量
      281         info.thread.free = 0;
      282         //任務(wù)
      283         info.task = {};
      284         //待處理任務(wù)數(shù)量
      285         info.task.count = 0;
      286 
      287         //獲取空閑"線程"數(shù)量
      288         for(i = 0, length = this.pool.length; i < length; i++){
      289             if(this.pool[i].free){
      290                 info.thread.free = info.thread.free + 1;
      291             }
      292         }
      293 
      294         //獲取任務(wù)數(shù)量(任務(wù)鏈長度)
      295         node = this.linkHead;
      296         if(node){
      297             info.task.count = info.task.count + 1;
      298             while(node.next){
      299                 info.task.count = info.task.count + 1;
      300                 node = node.next;
      301             }
      302         }
      303 
      304         return info;
      305     };
      306 
      307     /**
      308      * 創(chuàng)建節(jié)點
      309      * @param src 圖片路徑。字符串。
      310      * @param options 用戶自定義參數(shù)。包含:success回調(diào)、error回調(diào)、once標識。
      311      * @param notice 回調(diào)策略。 函數(shù)。
      312      * @param group 組信息。對象。{count: 0, success: [], error: []}
      313      * @param tr 出錯重試次數(shù)。數(shù)值。默認為0。
      314      * @returns {{}}
      315      */
      316     ImagePool.prototype.createNode = function(src, options, notice, group, tr){
      317         var node = {};
      318 
      319         node.src = src;
      320         node.options = options;
      321         node.notice = notice;
      322         node.group = group;
      323         node.try = tr || 0;
      324 
      325         return node;
      326     };
      327 
      328     /**
      329      * 向任務(wù)鏈表末尾追加節(jié)點
      330      * @param node 節(jié)點。對象。
      331      */
      332     ImagePool.prototype.appendNode = function(node){
      333         //判斷鏈表是否為空
      334         if(!this.linkHead){
      335             this.linkHead = node;
      336             this.linkNode = node;
      337         }else{
      338             this.linkNode.next = node;
      339             this.linkNode = node;
      340         }
      341     };
      342 
      343     /**
      344      * 刪除鏈表頭
      345      */
      346     ImagePool.prototype.shiftNode = function(){
      347         //判斷鏈表是否存在節(jié)點
      348         if(this.linkHead){
      349             //修改鏈表頭
      350             this.linkHead = this.linkHead.next || null;
      351         }
      352     };
      353 
      354     /**
      355      * 導(dǎo)出對外接口
      356      * @param max 最大連接數(shù)。數(shù)值。
      357      * @returns {{load: Function, info: Function}}
      358      */
      359     exports.initImagePool = function(max){
      360 
      361         if(!instance){
      362             instance = new ImagePool(max);
      363             instance.initPool();
      364         }
      365 
      366         return {
      367             /**
      368              * 加載圖片
      369              */
      370             load: function(){
      371                 instance.load.apply(instance, arguments);
      372             },
      373             /**
      374              * 內(nèi)部信息
      375              * @returns {*|any|void}
      376              */
      377             info: function(){
      378                 return instance.info.call(instance);
      379             }
      380         };
      381     };
      382 
      383 }(this));

       

      posted @ 2014-12-13 11:08  楊元  閱讀(4053)  評論(9)    收藏  舉報
      主站蜘蛛池模板: 泗阳县| 久青草精品视频在线观看| 久热这里只精品视频99| 国产精品久久久久久久网| 无线日本视频精品| 国产精品人成视频免费国产| 水蜜桃精品综合视频在线| 日韩精品一区二区三区激情视频| 亚洲欧美日韩综合久久久| 中文精品无码中文字幕无码专区| 亚洲精品一区二区毛豆| 与子乱对白在线播放单亲国产| 久久这里有精品国产电影网| 国产一区二区三区小说| 国产黄色av一区二区三区| 国产精品视频第一第二区| 视频一区视频二区在线视频| 中文字幕日韩精品东京热| 中文字幕日韩有码一区| 亚洲欧美精品综合在线观看| 最近中文字幕国产精品| 二区中文字幕在线观看| 国产成人精品久久一区二| 欧美怡春院一区二区三区| 日本久久99成人网站| 日本熟妇乱一区二区三区| 丝袜老师办公室里做好紧好爽| 97精品国产91久久久久久久| 日韩一区二区三区亚洲一| yy111111少妇无码影院| 国产成人亚洲精品成人区| 少妇激情一区二区三区视频小说 | 亚洲精品漫画一二三区| 高清自拍亚洲精品二区| 国产精品美女久久久久久麻豆| 一本无码在线观看| 色综合色国产热无码一| 少妇又爽又刺激视频| 精品久久精品久久精品九九| 狠狠躁日日躁夜夜躁欧美老妇| 亚洲欧美日韩在线不卡|