javascript 構(gòu)建一個(gè)xmlhttp對(duì)象池合理創(chuàng)建和使用xmlhttp對(duì)象
更新時(shí)間:2010年01月15日 16:33:39 作者:
在我的這篇舊文里曾經(jīng)發(fā)布了一個(gè)簡(jiǎn)單的ajax操作類。我們發(fā)現(xiàn),在舊文里創(chuàng)建xmlhttp對(duì)象的時(shí)候,每次都要new一個(gè)對(duì)象。而我們都知道new一個(gè)對(duì)象的開(kāi)銷是很大的。
如果我們?cè)诳蛻舳祟l繁使用ajax技術(shù),那么我們就不得不多次創(chuàng)建xmlhttp對(duì)象。當(dāng)然,如您所知,我們可以改進(jìn)創(chuàng)建的方式,比如使用全局變量來(lái)緩存一個(gè)實(shí)例(客戶端的單例模式?!),對(duì)于同步方式的通信,這是很有效的,但是這樣的方式對(duì)于異步通信會(huì)出現(xiàn)問(wèn)題,因?yàn)闆](méi)有了進(jìn)程的堵塞,用戶可能在上一次通信未完成時(shí)再次調(diào)用同一個(gè)xmlhttp實(shí)例,這樣不等前一個(gè)調(diào)用的回調(diào)函數(shù)觸發(fā),前一次調(diào)用就被“覆蓋”掉了(也就代表前一次調(diào)用失敗)。建立一個(gè)保持xmlhttp實(shí)例的池,好處顯而易見(jiàn),最明顯的優(yōu)點(diǎn)就是我們不會(huì)創(chuàng)建冗余對(duì)象,同時(shí)也不會(huì)出現(xiàn)在同一個(gè)正在被調(diào)用的xmlhttp實(shí)例上出現(xiàn)再次被操作的情況。
具體實(shí)現(xiàn)思路:
我們使用一個(gè)數(shù)組來(lái)存儲(chǔ)已創(chuàng)建的xmlhttp對(duì)象實(shí)例,然后每次調(diào)用從池中去取一個(gè)實(shí)例。xmlhttp實(shí)例通訊完畢后我們不用做任何處置,因?yàn)樗陨淼膔eadyState屬性可以標(biāo)識(shí)出它是否可用,如果當(dāng)時(shí)沒(méi)有空閑的xmlhttp實(shí)例,且池中的實(shí)例數(shù)小于最大實(shí)例個(gè)數(shù),那么就創(chuàng)建一個(gè)新的實(shí)例并放入池中。重新改進(jìn)的實(shí)現(xiàn)代碼如下:
//封裝XMLHTTP的MyAjaxObj類
var MyAjaxObj = new Object();
var maxXmlHttpCount = 5; //最多5個(gè)xmlhttp對(duì)象存在
MyAjaxObj.reqList = []; //可以清空里面的項(xiàng)
MyAjaxObj.getFreeObj = function() {
var req = null;
var len = this.reqList.length;
//先從當(dāng)前的池里取
for (var i = 0; i < len; i++) {
if (this.reqList[i]) {
if (this.reqList[i].readyState == 4 || this.reqList[i].readyState == 0) {
req = this.reqList[i];
break;
}
}
}
//如果沒(méi)有閑置的對(duì)象,自己獨(dú)立創(chuàng)建
if (req == null) {
if (this.reqList.length < maxXmlHttpCount) {
req = getXmlHttp();
this.reqList.push(req);
}
}
return req;
}
//創(chuàng)建一個(gè)XMLHTTP對(duì)象,兼容不同的瀏覽器
function getXmlHttp() {
var xmlHttp = false;
var arrSignatures = ["MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0",
"MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP",
"Microsoft.XMLHTTP"];
for (var i = 0; i < arrSignatures.length; i++) {
try {
xmlHttp = new ActiveXObject(arrSignatures[i]);
return xmlHttp;
}
catch (oError) {
xmlHttp = false; //ignore
}
}
// throw new Error("MSXML is not installed on your system.");
if (!xmlHttp && typeof XMLHttpRequest != 'undefined') {
xmlHttp = new XMLHttpRequest();
}
return xmlHttp;
}
/*封裝XMLHTTP向服務(wù)器發(fā)送請(qǐng)求的操作
url:向服務(wù)器請(qǐng)求的路徑;method:請(qǐng)求的方法,即是get/post;***callback:當(dāng)服務(wù)器成功返回結(jié)果時(shí),調(diào)用的函數(shù)(類似c#回調(diào)函數(shù))***
data:向服務(wù)器請(qǐng)求時(shí)附帶的數(shù)據(jù);urlencoded:url是否編碼;cached:是否使用緩存; callBackError;當(dāng)服務(wù)器返回錯(cuò)誤時(shí)調(diào)用的函數(shù)
*/
MyAjaxObj.send = function(url, method, callback, data, urlencoded, cached, callBackError) {
var req = this.getFreeObj(); //從池里或者直接實(shí)例化一個(gè)XMLHTTP的實(shí)例
//當(dāng)XMLHTTP的請(qǐng)求狀態(tài)發(fā)生改變時(shí)調(diào)用 (核心處理函數(shù))
req.onreadystatechange = function() {
// 當(dāng)請(qǐng)求已經(jīng)加載
if (req.readyState == 4) {
// 當(dāng)請(qǐng)求返回成功
if (req.status == 200) { //或者 req.status < 400
// 當(dāng)定義了成功回調(diào)函數(shù)時(shí),執(zhí)行成功回調(diào)函數(shù)
if (callback)
callback(req, data);
}
// 當(dāng)請(qǐng)求返回錯(cuò)誤
else {
//當(dāng)定義了失敗回調(diào)函數(shù)時(shí),執(zhí)行失敗回調(diào)函數(shù)
if (callBackError)
callBackError(req, data);
}
// 有池的管理,我們可以省卻釋放資源的方法
// try {
// delete req;
// req = null;
// }
// catch (e) {
// alert(e.message);
// }
}
}
//如果以POST方式回發(fā)服務(wù)器
if (method.toUpperCase() == "POST") {
req.open("POST", url, true);
//請(qǐng)求是否需要緩存(只有在req.open之后才可以設(shè)置此項(xiàng))
if (cached)
req.setRequestHeader("If-Modified-Since", "0");
//請(qǐng)求需要編碼
if (urlencoded)
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req.send(data);
MyAjaxObj.reqList.push(req);
}
//以GET方式請(qǐng)求
else {
req.open("GET", url, true);
//請(qǐng)求是否需要緩存
if (cached)
req.setRequestHeader("If-Modified-Since", "0");
req.send(null);
MyAjaxObj.reqList.push(req);
}
return req;
}
//全部清除XMLHTTP數(shù)組元素,釋放資源
MyAjaxObj.clearReqList = function() {
var len = MyAjaxObj.reqList.length;
for (var i = 0; i < len; i++) {
var req = MyAjaxObj.reqList[i];
if (req) {
try {
delete req;
} catch (e) { }
}
}
MyAjaxObj.reqList = [];
}
//進(jìn)一步封裝XMLHTTP以POST方式發(fā)送請(qǐng)求時(shí)的代碼
//isClear:是否清除XMLHTTP數(shù)組的所有元素;其他參數(shù)的意義見(jiàn) MyAjaxObj.send
MyAjaxObj.sendPost = function(url, data, callback, isClear, isCached, callBackError) {
if (isClear) {
MyAjaxObj.clearReqList();
}
MyAjaxObj.send(url, "POST", callback, data, true, isCached, callBackError); //post方法需要編碼
}
//進(jìn)一步封裝XMLHTTP以GET方式發(fā)送請(qǐng)求時(shí)的代碼
MyAjaxObj.sendGet = function(url, args, callback, isClear, isCached, callBackError) {
if (isClear)
MyAjaxObj.clearReqList();
return MyAjaxObj.send(url, "GET", callback, args, false, isCached, callBackError);
}
最后再ps:上周周末和一個(gè)哥們聊天的時(shí)候談到ajax應(yīng)用中的xmlhttp對(duì)象。那哥們ms很“虔誠(chéng)”地問(wèn)我說(shuō)xmlhttp怎么就異步通信了。我當(dāng)時(shí)竟然毫不思索地說(shuō)因?yàn)檫@個(gè)對(duì)象處理我們的請(qǐng)求調(diào)用是“異步”的(當(dāng)然可以設(shè)置成同步的,不過(guò)這是一句廢話),當(dāng)前這個(gè)請(qǐng)求不會(huì)影響其他的操作。這個(gè)回答是很“官方”的,顯然沒(méi)有說(shuō)到問(wèn)題的本質(zhì)。哥們,您的眼神兒有必要那么bs人么?現(xiàn)在稍作分析,個(gè)人認(rèn)為其實(shí)每個(gè)xmlhttp異步請(qǐng)求都會(huì)觸發(fā)一個(gè)回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)的調(diào)用不影響其他的操作,這個(gè)方法才是“異步”。如果對(duì)比c#里的異步處理回調(diào)方法,它們?cè)谠砩掀鋵?shí)是相通的。 哈哈,現(xiàn)在終于想通了, 真是太驕傲,太有出息了,想到就興奮!
具體實(shí)現(xiàn)思路:
我們使用一個(gè)數(shù)組來(lái)存儲(chǔ)已創(chuàng)建的xmlhttp對(duì)象實(shí)例,然后每次調(diào)用從池中去取一個(gè)實(shí)例。xmlhttp實(shí)例通訊完畢后我們不用做任何處置,因?yàn)樗陨淼膔eadyState屬性可以標(biāo)識(shí)出它是否可用,如果當(dāng)時(shí)沒(méi)有空閑的xmlhttp實(shí)例,且池中的實(shí)例數(shù)小于最大實(shí)例個(gè)數(shù),那么就創(chuàng)建一個(gè)新的實(shí)例并放入池中。重新改進(jìn)的實(shí)現(xiàn)代碼如下:
復(fù)制代碼 代碼如下:
//封裝XMLHTTP的MyAjaxObj類
var MyAjaxObj = new Object();
var maxXmlHttpCount = 5; //最多5個(gè)xmlhttp對(duì)象存在
MyAjaxObj.reqList = []; //可以清空里面的項(xiàng)
MyAjaxObj.getFreeObj = function() {
var req = null;
var len = this.reqList.length;
//先從當(dāng)前的池里取
for (var i = 0; i < len; i++) {
if (this.reqList[i]) {
if (this.reqList[i].readyState == 4 || this.reqList[i].readyState == 0) {
req = this.reqList[i];
break;
}
}
}
//如果沒(méi)有閑置的對(duì)象,自己獨(dú)立創(chuàng)建
if (req == null) {
if (this.reqList.length < maxXmlHttpCount) {
req = getXmlHttp();
this.reqList.push(req);
}
}
return req;
}
//創(chuàng)建一個(gè)XMLHTTP對(duì)象,兼容不同的瀏覽器
function getXmlHttp() {
var xmlHttp = false;
var arrSignatures = ["MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0",
"MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP",
"Microsoft.XMLHTTP"];
for (var i = 0; i < arrSignatures.length; i++) {
try {
xmlHttp = new ActiveXObject(arrSignatures[i]);
return xmlHttp;
}
catch (oError) {
xmlHttp = false; //ignore
}
}
// throw new Error("MSXML is not installed on your system.");
if (!xmlHttp && typeof XMLHttpRequest != 'undefined') {
xmlHttp = new XMLHttpRequest();
}
return xmlHttp;
}
/*封裝XMLHTTP向服務(wù)器發(fā)送請(qǐng)求的操作
url:向服務(wù)器請(qǐng)求的路徑;method:請(qǐng)求的方法,即是get/post;***callback:當(dāng)服務(wù)器成功返回結(jié)果時(shí),調(diào)用的函數(shù)(類似c#回調(diào)函數(shù))***
data:向服務(wù)器請(qǐng)求時(shí)附帶的數(shù)據(jù);urlencoded:url是否編碼;cached:是否使用緩存; callBackError;當(dāng)服務(wù)器返回錯(cuò)誤時(shí)調(diào)用的函數(shù)
*/
MyAjaxObj.send = function(url, method, callback, data, urlencoded, cached, callBackError) {
var req = this.getFreeObj(); //從池里或者直接實(shí)例化一個(gè)XMLHTTP的實(shí)例
//當(dāng)XMLHTTP的請(qǐng)求狀態(tài)發(fā)生改變時(shí)調(diào)用 (核心處理函數(shù))
req.onreadystatechange = function() {
// 當(dāng)請(qǐng)求已經(jīng)加載
if (req.readyState == 4) {
// 當(dāng)請(qǐng)求返回成功
if (req.status == 200) { //或者 req.status < 400
// 當(dāng)定義了成功回調(diào)函數(shù)時(shí),執(zhí)行成功回調(diào)函數(shù)
if (callback)
callback(req, data);
}
// 當(dāng)請(qǐng)求返回錯(cuò)誤
else {
//當(dāng)定義了失敗回調(diào)函數(shù)時(shí),執(zhí)行失敗回調(diào)函數(shù)
if (callBackError)
callBackError(req, data);
}
// 有池的管理,我們可以省卻釋放資源的方法
// try {
// delete req;
// req = null;
// }
// catch (e) {
// alert(e.message);
// }
}
}
//如果以POST方式回發(fā)服務(wù)器
if (method.toUpperCase() == "POST") {
req.open("POST", url, true);
//請(qǐng)求是否需要緩存(只有在req.open之后才可以設(shè)置此項(xiàng))
if (cached)
req.setRequestHeader("If-Modified-Since", "0");
//請(qǐng)求需要編碼
if (urlencoded)
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req.send(data);
MyAjaxObj.reqList.push(req);
}
//以GET方式請(qǐng)求
else {
req.open("GET", url, true);
//請(qǐng)求是否需要緩存
if (cached)
req.setRequestHeader("If-Modified-Since", "0");
req.send(null);
MyAjaxObj.reqList.push(req);
}
return req;
}
//全部清除XMLHTTP數(shù)組元素,釋放資源
MyAjaxObj.clearReqList = function() {
var len = MyAjaxObj.reqList.length;
for (var i = 0; i < len; i++) {
var req = MyAjaxObj.reqList[i];
if (req) {
try {
delete req;
} catch (e) { }
}
}
MyAjaxObj.reqList = [];
}
//進(jìn)一步封裝XMLHTTP以POST方式發(fā)送請(qǐng)求時(shí)的代碼
//isClear:是否清除XMLHTTP數(shù)組的所有元素;其他參數(shù)的意義見(jiàn) MyAjaxObj.send
MyAjaxObj.sendPost = function(url, data, callback, isClear, isCached, callBackError) {
if (isClear) {
MyAjaxObj.clearReqList();
}
MyAjaxObj.send(url, "POST", callback, data, true, isCached, callBackError); //post方法需要編碼
}
//進(jìn)一步封裝XMLHTTP以GET方式發(fā)送請(qǐng)求時(shí)的代碼
MyAjaxObj.sendGet = function(url, args, callback, isClear, isCached, callBackError) {
if (isClear)
MyAjaxObj.clearReqList();
return MyAjaxObj.send(url, "GET", callback, args, false, isCached, callBackError);
}
最后再ps:上周周末和一個(gè)哥們聊天的時(shí)候談到ajax應(yīng)用中的xmlhttp對(duì)象。那哥們ms很“虔誠(chéng)”地問(wèn)我說(shuō)xmlhttp怎么就異步通信了。我當(dāng)時(shí)竟然毫不思索地說(shuō)因?yàn)檫@個(gè)對(duì)象處理我們的請(qǐng)求調(diào)用是“異步”的(當(dāng)然可以設(shè)置成同步的,不過(guò)這是一句廢話),當(dāng)前這個(gè)請(qǐng)求不會(huì)影響其他的操作。這個(gè)回答是很“官方”的,顯然沒(méi)有說(shuō)到問(wèn)題的本質(zhì)。哥們,您的眼神兒有必要那么bs人么?現(xiàn)在稍作分析,個(gè)人認(rèn)為其實(shí)每個(gè)xmlhttp異步請(qǐng)求都會(huì)觸發(fā)一個(gè)回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)的調(diào)用不影響其他的操作,這個(gè)方法才是“異步”。如果對(duì)比c#里的異步處理回調(diào)方法,它們?cè)谠砩掀鋵?shí)是相通的。 哈哈,現(xiàn)在終于想通了, 真是太驕傲,太有出息了,想到就興奮!
您可能感興趣的文章:
- java實(shí)現(xiàn)輕量型http代理服務(wù)器示例
- java使用httpclient模擬post請(qǐng)求和get請(qǐng)求示例
- JAVA發(fā)送HTTP請(qǐng)求,返回HTTP響應(yīng)內(nèi)容,應(yīng)用及實(shí)例代碼
- java使用httpclient發(fā)送post請(qǐng)求示例
- 使用flex中的httpservice方法與java進(jìn)行交互
- javascript創(chuàng)建createXmlHttpRequest對(duì)象示例代碼
- javaScript如何生成xmlhttp
- 基于JAVA中Jersey處理Http協(xié)議中的Multipart的詳解
- 使用java實(shí)現(xiàn)http多線程斷點(diǎn)下載文件(二)
- 使用java實(shí)現(xiàn)http多線程斷點(diǎn)下載文件(一)
- Java如何實(shí)現(xiàn)HTTP斷點(diǎn)續(xù)傳功能
- JavaScript下通過(guò)的XMLHttpRequest發(fā)送請(qǐng)求的代碼
- javascript一個(gè)無(wú)懈可擊的實(shí)例化XMLHttpRequest的方法
- javascript XMLHttpRequest對(duì)象全面剖析
- javascript對(duì)XMLHttpRequest異步請(qǐng)求的面向?qū)ο蠓庋b
- Javascript+XMLHttpRequest+asp.net無(wú)刷新讀取數(shù)據(jù)庫(kù)數(shù)據(jù)
- 使用asx3m與xstream配合解決flex與java利用httpservice傳遞xml數(shù)據(jù)問(wèn)題
- java使用http實(shí)現(xiàn)文件下載學(xué)習(xí)示例
相關(guān)文章
layui的表單驗(yàn)證支持ajax判斷用戶名是否重復(fù)的實(shí)例
今天小編就為大家分享一篇layui的表單驗(yàn)證支持ajax判斷用戶名是否重復(fù)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09js canvas實(shí)現(xiàn)畫(huà)圖、濾鏡效果
這篇文章主要為大家詳細(xì)介紹了js canvas實(shí)現(xiàn)畫(huà)圖、濾鏡效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11JavaScript不同場(chǎng)景下的文件下載方案詳解
這篇文章主要為大家詳細(xì)介紹了JavaScript中不同場(chǎng)景下的三種常見(jiàn)文件下載方案,文中的示例代碼講解詳細(xì),有需要的小伙伴可以參考一下2023-12-12web3.js增加eth.getRawTransactionByHash(txhash)方法步驟
這篇文章主要介紹了web3.js增加eth.getRawTransactionByHash(txhash)方法步驟,需要的朋友可以參考下2018-03-03JavaScript實(shí)現(xiàn)拖拽簡(jiǎn)單效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)拖拽簡(jiǎn)單效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09JavaScript事件學(xué)習(xí)小結(jié)(一)事件流
這篇文章主要介紹了JavaScript事件學(xué)習(xí)小結(jié)(一)事件流的相關(guān)資料,需要的朋友可以參考下2016-06-06JavaScript實(shí)現(xiàn)左側(cè)菜單效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)左側(cè)菜單效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12