Javascript 为什么通过XHR';s异步onreadystatechange事件是否使用堆栈?
我在一些(但不是所有)IE7机器上遇到堆栈溢出错误 此函数用于下载大量基于URL的资源,但不处理这些资源。它在我的登录页面上运行,其目的是在键入凭据时获取静态内容,以便在您确实需要它时,浏览器可以从其本地缓存中获取它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
// 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()是不必要的。