我已经看过很多关于这个主题的文章,但它们都已经存在了很多年,所以我认为有更新的东西是明智的。
我正在寻找一个简单,无懈可击,跨浏览器(IE 8+)的XMLHttpRequest,没有内存泄漏。我使用我在各个地方获得的信息(包括https://github.com/ilinsky/xmlhttprequest)将下面的内容放在一起,以获取有关内存泄漏和http://www.quirksmode.org/js/xmlhttp.html的信息。
此代码有效,但我发现它认为这仍然有内存泄漏。我不太擅长阅读Chrome中的内存使用信息,所以我希望有人可以协助我进行验证。
var nXHR = nXHR || (function(){
// keep track of each instance
var instanceID = 0, runningXHRs = {};
// the various ways to create an XMLHttpRequest object
var createXHRObject = [
function(){ return new XMLHttpRequest() },
function(){ return new ActiveXObject("Msxml2.XMLHTTP") },
function(){ return new ActiveXObject("Msxml3.XMLHTTP") },
function(){ return new ActiveXObject("Microsoft.XMLHTTP") }
];
// find the one that works
for(var i = 0, numTypes = createXHRObject.length; i < numTypes; ++i)
{
try
{
createXHRObject[i]().close;
createXHRObject = createXHRObject[i];
break;
}
catch(e)
{
continue;
}
}
// make sure we found one
if(Object.prototype.toString.call(createXHRObject) != "[object Function]")
{
alert("ERROR: Unable to find a suitable way to create an XMLHttpRequest object.");
return;
}
// we need to clean up memory on window unload
var onWindowUnload = function()
{
for(var i in runningXHRs)
{
runningXHRs[i].onreadystatechange = new window.Function;
}
};
// cross browser to attach the event
if(window.addEventListener)
{
window.addEventListener("unload", onWindowUnload);
}
else
{
window.attachEvent("onunload", function(){ onWindowUnload.call(window) });
}
/* return a function to make an actual call
*
* url = url
* onComplete = function({
* "success" : xhr.status == 200,
* "status" : xhr.status,
* "text" : xhr.responseText,
* "xml" : xhr.this.responseXML
* })
* options = {
* "async" : true || false,
* "postData" : "",
* "requestHeaders" : {
* "headerName" : "headerValue",
* "headerName" : "headerValue",
* "headerName" : "headerValue",
* ...
* }
* }
*/
return function(url, onComplete, options)
{
var options = options || {};
// is this an async call
var async = options.async === false ? false : true;
// current instance
var thisInstanceID = ++instanceID;
// create an xhr
var xhr = createXHRObject();
// save it for future access
runningXHRs[thisInstanceID] = xhr;
// open it
xhr.open(options.postData ? "POST" : "GET", url, async);
// set a global user-agent header
xhr.setRequestHeader("User-Agent", "XMLHTTP/1.0");
// if we're posting data then set the content-type header
if(options.postData)
{
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
}
// set user provided headers
for(headerName in options.requestHeaders)
{
xhr.setRequestHeader(headerName, options.requestHeaders[headerName]);
}
// on state change
xhr.onreadystatechange = function()
{
// if we're not done then continue
if(this.readyState != 4) return;
// if we're done then run the onComplete function
onComplete({
"success" : this.status == 200,
"status" : this.status,
"text" : this.responseText,
"xml" : this.responseXML
});
// clean up to avoid memory leaks
this.onreadystatechange = new window.Function;
// we're done so remove it from the running list
delete runningXHRs[thisInstanceID];
};
if(xhr.readyState == 4) return;
// do it
xhr.send(options.postData);
};
})();
测试用例:
<html>
<head>
<script type="text/javascript" src="nXHR.js"></script>
<script type="text/javascript">
function doIt()
{
nXHR("http://www.google.com", onDone);
nXHR("http://www.mozilla.org", onDone);
}
function onDone(data)
{
alert(data.success + "\n" + data.text.length);
}
</script>
</head>
<body>
<a href="#" onclick="doIt(); return false;">click me</a>
</body>
</html>