Javascript 为什么通过XHR';s异步onreadystatechange事件是否使用堆栈?

Javascript 为什么通过XHR';s异步onreadystatechange事件是否使用堆栈?,javascript,xmlhttprequest,dom-events,stack-overflow,Javascript,Xmlhttprequest,Dom Events,Stack Overflow,我在一些(但不是所有)IE7机器上遇到堆栈溢出错误 此函数用于下载大量基于URL的资源,但不处理这些资源。它在我的登录页面上运行,其目的是在键入凭据时获取静态内容,以便在您确实需要它时,浏览器可以从其本地缓存中获取它 // Takes an array of resources URLs and preloads them sequentially, // but asynchronously, using an XHR object. function preloadResources(res

我在一些(但不是所有)IE7机器上遇到堆栈溢出错误

此函数用于下载大量基于URL的资源,但不处理这些资源。它在我的登录页面上运行,其目的是在键入凭据时获取静态内容,以便在您确实需要它时,浏览器可以从其本地缓存中获取它

// Takes an array of resources URLs and preloads them sequentially,
// but asynchronously, using an XHR object.
function preloadResources(resources) {

    // Kick it all off.
    if (resources.length > 0) {
        var xhr = getXHRObject(); // Prepare the XHR object which will be reused for each request.
        xhr.open('GET', resources.shift(), true);
        xhr.onreadystatechange = handleReadyStateChange;
        xhr.send(null);
    }

    // Handler for the XHR's onreadystatechange event.  Loads the next resource, if any.
    function handleReadyStateChange() {
        if (xhr.readyState == 4) {
            if (resources.length > 0) {
                xhr.open('GET', resources.shift(), true);
                xhr.onreadystatechange = arguments.callee;
                xhr.send(null);
            }
        }
    }

    // A safe cross-browser way to get an XHR object.
    function getXHRObject() {
        // Clipped for clarity.
    }

} // End preloadResources().
它的名字是这样的:

preloadResources([
    'http://example.com/big-image.png',
    'http://example.com/big-stylesheet.css',
    'http://example.com/big-script.js']);
它递归地处理URL数组。我认为它不容易受到堆栈溢出错误的影响,因为每个递归都是从异步事件调用的——XHR的
onreadystatechange
事件(请注意,我正在异步调用
XHR.open()
)。我觉得这样做会阻止它增加堆栈


我看不出堆栈是如何失控的我哪里出错了?

您是否可以通过控制台记录或提醒
参数的值。被调用方
?我很好奇如果它从
preload resources()
函数而不是
handleReadyStateChange()
解析为
参数
变量,会发生什么。对我来说似乎不太可能,但只要看一眼你的代码,它就会跳出来

但是,为了回答您的问题,我认为上面代码中的一个错误做法是重用XmlHttpRequest对象,尤其是在不让生命周期完成或调用
xhr.abort()
的情况下。那是一个不,不,我刚才藏起来了。在这里和网上的各个地方都有讨论。请注意,IE尤其不能很好地重用xhr。看

希望这有帮助


Scott使用计时器执行递归可以防止出现堆栈溢出问题

// Handler for the XHR's onreadystatechange event.  Loads the next resource, if any.
function handleReadyStateChange() {
    if (xhr.readyState == 4 && resources.length > 0) {
        setTimeout(function() {
            xhr.open('GET', resources.shift(), true);
            xhr.onreadystatechange = handleReadyStateChange;
            xhr.send(null);
        }, 10);
    }
}

我猜将XHR请求彼此链接会消耗堆栈。用定时器将它们链接在一起可以防止这种情况——至少在IE7中是这样。我没有在其他浏览器上看到这个问题,所以我不知道。

谢谢您的回复,Scott<代码>参数。正确计算被调用方。关于您引用的文章,原始文章的作者写道,调用
xhr.open()
后,您不必为
onreadystatechange
设置处理程序,因为xhr.abort()是不必要的。