跨浏览器(IE 8+)XMLHttpRequest,没有内存泄漏

时间:2016-01-13 04:23:22

标签: javascript memory-leaks cross-browser xmlhttprequest

我已经看过很多关于这个主题的文章,但它们都已经存在了很多年,所以我认为有更新的东西是明智的。

我正在寻找一个简单,无懈可击,跨浏览器(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>

0 个答案:

没有答案