JavaScript設計模式(4)
阿新 • • 發佈:2018-03-02
元素 end java 監聽器 post text HR ole abort
橋接模式
在設計一個 Js API 時,可用來弱化它與使用它的類和對象之間的耦合
1. 事件監聽器的回調函數
function getBeerById(id, callback) {
asyncRequest(‘GET‘, ‘beer.uri?id=‘ + id, function(res){
callback(resp.responseText)
})
}
function getBeerByIdBridge (e) { // 橋接元素:事件監聽器的回調函數
// 避免把 this.id 耦合到函數 getBeerById 中
getBeerById (this.id, function(beer) {
console.log(‘Requested Beer: ‘ + beer)
})
}
addEvent(element, ‘click‘, getBeerByIdBridge);
2. 橋接性函數:特權函數
var Public = function() {
var secret = 3;
this.privilegedGetter = function() {
return secret
}
}
// usage
var o = new Public;
var data = o.privilegedGetter()
3. 用橋接模式聯結多個類
var Class1 = function(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
}
var Class2 = function(d) {
this.d = d;
}
var BridgeClass = function(a, b, c, d) {
this.one = new Class1(a, b, c);
this.two = new Class2(d)
}
4. 構建 XHR 連接隊列
// 獲取 xhr 對象函數
var asyncRequest = (function() {
function handleReadyState(o, callback) { // 其實也可以用 xhr.onreadystatechange 來實現而不用 setInterval 來監聽 xhr 的 readyState
var poll = window.setInterval(function(){
if(o && o.readyState == 4) {
window.clearInterval(poll);
if(callback) {
callback(o)
}
}
}, 50);
}
var getXHR = function() {
var http;
try {
http = new XMLHttpRequest;
getXHR = function() { // memoizing
return new XMLHttpRequest;
}
}catch(e) {
var msxml = [
‘MSXML2.XMLHTTP‘,
‘MSXML2.XMLHTTP.3.0‘,
‘Microsoft.XMLHTTP‘
];
for(var i=0, len = msxml.length; i<len; i++) {
try {
http = new ActiveXObject(msxml[i]);
getXHR = function() {
return new ActiveXObject(msxml[i]);
};
break
}catch(e) {
continue;
}
}
}
return http;
};
return function(method, url, callback, postData) {
var http = getXHR();
http.open(method, url, true);
handleReadyState(http, callback);
http.send(postData || null);
return http;
}
})()
Function.prototype.method = function(name, fn) {
this.prototype[name] = fn;
return this
}
// 實現隊列
DED.Queue = function() {
this.queue = [];
this.retryCount = 3;
this.currentRetry = 0;
this.paused = false;
this.timeout = 5000;
this.conn = {};
this.timer = {};
}
DED.Queue.method(‘flush‘, function(){
if(!this.queue.length > 0) { // 當隊列長度等於 0 時進入 if
return;
}
if(this.paused) {
this.paused = false;
return
}
var that = this;
this.currentRetry++;
// 如果在規定次數內,則繼續重復請求,否則結束當前該請求
var abort = function() {
that.conn.abort(); // 終止該請求,readyState 屬性將被置為 0
if(that.currentRetry == that.retryCount) {
// that.onFailure.fire();
console.log(‘failure: ‘ + that.queue[0].url)
that.currentRetry = 0;
} else {
that.flush();
}
}
var callback = function (o) {
document.getElementById(‘feed-readers‘).innerText = o.response
console.log(o)
// 停止超時處理程序
window.clearTimeout(that.timer);
that.currentRetry = 0;
// 剔除當前請求成功的請求項
that.queue.shift();
// that.onFlush.fire(o.responseText);
if(that.queue.length == 0) {
// that.onComplete.fire();
return;
}
// 繼續新的請求
that.flush()
}
this.conn = asyncRequest(
this.queue[0][‘method‘],
this.queue[0][‘url‘],
callback,
this.queue[0][‘params‘]
)
this.timer = window.setTimeout(abort, this.timeout);
}).method(‘setRetryCount‘, function(count) {
this.retryCount = count;
}).method(‘setTimeout‘, function(time) {
this.timeout = time;
}).method(‘add‘, function(o) {
this.queue.push(o);
}).method(‘pause‘, function() {
this.paused = true;
}).method(‘dequeue‘, function() {
this.queue.pop()
}).method(‘clear‘, function() {
this.queue = []
})
// usage
var q = new DED.Queue;
q.setRetryCount(3);
q.setTimeout(1000);
q.add({
method: ‘GET‘,
‘url‘: ‘https://www.baidu.com‘,
});
q.add({
method: ‘GET‘,
‘url‘: ‘https://www.baidu.com?xiaoming‘,
});
q.flush()
// 在真實使用中,可以在添加事件的時候使用橋接函數;
// 也可以提供一個動作調度函數,橋接用戶操作所包含的輸入信息並將其委托給恰當的處理代碼。
5. 橋接模式的利與弊
- 利:
- 將抽象與其實現隔離開,有助於獨立地管理軟件的各個部分
- Bug更容易查找
- 促進代碼的模塊化,提高抽象的靈活度
- 可以用來把一組類和函數連接起來,而且提供了一種借助於特權函數訪問私有數據的手段
- 弊:
- 增加了函數調用次數,對性能有一些負面影響
- 提高了系統的復雜度
- 不可濫用
註意
轉載、引用,但請標明作者和原文地址
JavaScript設計模式(4)