代理模式是在请求对象与响应对象之间添加一个对象,负责接受请求,进行一定处理后再发送请求。如缓存,图片预加载,合并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:代理和本体接口应该一致,当不需要代理时,可直接使用本体
网友评论