JavaScript代理模式

2020-12-29  本文已影响0人  晓蟲QwQ

代理模式是在请求对象与响应对象之间添加一个对象,负责接受请求,进行一定处理后再发送请求。如缓存,图片预加载,合并HTTP请求,拒绝非法请求等。

虚拟代理实现图片预加载

var myImage = (function(){
    var imgNode = document.createElement('img');
    document.body.appendChild(imgNode);
    
    return {
        setSrc: function( src ){
            imgNode.src = src;
        }
    }
})();

var proxyImage = (function(){
    var img = new Image;
    img.onload = function(){
        myImage.setSrc(this.src);
    }
    return {
        setSrc: function( src ){
            myImage.setSrc( 'loading.gif' );
            img.src = src;
        }
    }
})();

proxyImage.setSrc('resour.jpg');

虚拟代理合并HTTP请求

<input type="checkbox" id="1" />1
<input type="checkbox" id="2" />2
<input type="checkbox" id="3" />3
<input type="checkbox" id="4" />4
<input type="checkbox" id="5" />5
<input type="checkbox" id="6" />6
<input type="checkbox" id="7" />7
var synchronousFile = function( id ){
    console.log( '开始同步文件,id为:' + id );
};

var proxySynchronousFile = (function() {
    var cache = [],   // 保存一段时间内需要同步的ID
        timer;        // 定时器
    
    return function( id ){
        cache.push( id );
        if( timer ){      // 保证不会覆盖已经启动的定时器
            return;
        }
        
        timer = setTimeout(function(){
            synchronousFile( cache.join(';'));      // 2秒后向本体发送需要同步的ID集合
            clearImmediate( timer );    // 清空定时器
            timer = null;
            cache.length = 0;  // 清空ID集合
        },2000);
    }
})();

var checkbox = document.getElementsByTagName('input');

for( var i = 0,c; c = checkbox[ i++ ]; ){
    c.onclick = function(){
        if ( this.checked === true ){
            proxySynchronousFile( this.id );
        }
    }
}

虚拟代理惰性加载js文件

代理接受请求,未必需要返回响应,代理在请求需要响应时才去下载对应js文件,并将请求提交到本体。

以下代码在接受请求后并不会返回响应,只有在按下F2时才会下载应用并提交请求,返回响应

var miniConsole = (function(){
    var cache = [];
    var handler = function(ev){
        if( ev.keyCode === 113 ){
            var script = document.createElement('script');
            script.onload = function(){
                for( var i = 0,fn;fn = cache[ i++ ];){
                    fn();
                }
            };
            script.src = 'miniConsole.js';
            document.getElementsByTagName('head')[0].appendChild( script );
            document.body.removeEventListener('keydown', handler); //只加载一次miniConsole.js
        }
    };
    
    document.body.addEventListener('keydown',handler,false);
    
    return {
        log: function(){
            var args = arguments;
            cache.push(function(){
                return miniConsole.log.apply( miniConsole, args );
            });
        }
    }
})();

//miniConsole.js代码。 当该文件下载完成后,miniConsole会被替换
miniConsole = {
    log:function(){
        //真正代码略
        console.log( Array.prototype.join.call( arguments ));
    }
}

缓存代理

/*************计算乘积************/
var mult = function(){
    var a = 1;
    for( var i = 0, l = arguments.length;i < l; i++){
        a = a * arguments[i];
    }
    return a;
}

/************计算加和************/
var plus = function(){
    var a = 0;
    for ( var i = 0, l = arguments.length; i < l; i++){
        a = a + arguments[i];
    }
    return a;
};

/*************** 创建缓存代理的工厂 ************/
var createProxyFactory = function( fn ){
    var cache = {};
    return function(){
        var args = Array.prototype.join.call( arguments, ',');
        if ( args in cache){
            return cache[args];
        }
        return cache[ args ] = fn.appl( this, arguments );
    }
};

var proxyMult = createProxyFactory( mult ),
proxyPlus = createProxyFactory( plus );

alert( proxyMult( 1, 2, 3, 4) );   //输出:24
alert( proxyMult( 1, 2, 3, 4) );    //输出:24
alert( proxyPlus( 1, 2, 3, 4) );    //输出:10
alert( proxyPlus( 1, 2, 3, 4) );    //输出:10

ps:代理和本体接口应该一致,当不需要代理时,可直接使用本体

上一篇 下一篇

猜你喜欢

热点阅读