什么是代理模式

代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。

代理和本体接口保持一致,那么用户可以放心的请求代理,他只关心是否得到想要的结果;在任何使用本体的地方都可以替换成使用代理。

虚拟代理:例如实现图片预加载、合并http请求。

缓存代理:例如缓存ajax异步请求的数据,下次再打开同一页的时候,便可以直接使用之前的数据。

面向对象例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
export class LoadImage{
setUrl(url, target) {
target.src = url;
}
}

export class LoadImageProxy{
constructor() {
this.loadImage = new LoadImage();
}

setUrl(url, target) {
this.loadImage.setUrl('./image/p2.gif', target);
let img = new Image();
img.onload = () => {
setTimeout(() => {
this.loadImage.setUrl(url, target);
}, 2000);
}
img.src = url;
}
}

export class LoadData{
constructor() {
this.data = {
renhong: {
name: 'renhongl',
age: 18
},
mogu: {
name: 'mogu',
age: 19
}
};
}

load(name, callback) {
setTimeout(() => {
callback(this.data[name]);
}, 2000);
}
}

export class LoadDataProxy{
constructor() {
this.loadData = new LoadData();
this.cache = {};
}

load(name, callback) {
if (!this.cache[name]) {
this.loadData.load(name, (data) => {
this.cache[name] = data;
callback(data);
});
} else {
callback(this.cache[name]);
}
}
}

函数式例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
* 使用虚拟代理实现图片预加载
* 使用缓存代理实现ajax异步请求数据
*/
(function () {

var logoImg = (function () {
var logo = document.querySelector('.logo');
return {
setSrc: function (src) {
setTimeout(function () {
logo.src = src;
});
}
}
})();

var proxyLogoImg = (function () {
var img = new Image();
img.onload = function () {
logoImg.setSrc(this.src);
}
return {
setSrc: function (src) {
logoImg.setSrc('./loading.png');
setTimeout(function () {
img.src = src;
}, 3000);
}
}
})();

var fetchData = (function () {
return {
start: function (url, fn) {
fetch(url).then(function (response) {
if (response.ok) {
response.json().then(function (data) {
setTimeout(function () {
fn.call(this, data);
}, 2000);
});
}
}).catch(function (err) {
console.log(err);
});
}
}
})();

var proxyFetchData = (function () {
var cache = {};
return {
start: function (url, fn) {
var key = url.split('.')[0];
if (key in cache) {
fn.call(this, cache[key]);
} else {
fetchData.start(url, function (data) {
cache[key] = data;
fn.call(this, data);
});
}
}
}
})();

var fetchDataAction = function () {
console.time('fetchData');
proxyFetchData.start('./1.json', function (data) {
console.log(data);
console.timeEnd('fetchData');
});
};

var init = function () {
proxyLogoImg.setSrc('./logo.png');
fetchDataAction();
setTimeout(function () {
fetchDataAction();
}, 5000);
};

init();

})();