为什么XMLHttpRequest.abort阻止除循环内第一个内容以外的所有Ajax调用
问题描述:
我正在修改通过发送虚假Ajax请求来实现Javascript中的线程。不过,我对下面的代码的行为感到惊讶。为什么XMLHttpRequest.abort阻止除循环内第一个内容以外的所有Ajax调用
随着xhr.abort()注释掉,“季度”和“半”都会像我期望的那样穿插到控制台。但是如果调用xhr.abort(),则只有“季度”被发送到控制台,而不是“一半”。
任何人都可以深入了解XMLHttpRequest的中止方法是如何工作的,或者可以理解的情况。我查看了https://developer.mozilla.org/en/DOM/XMLHttpRequest的文档,它说“如果已经发送请求,abort()...将中止请求。”关键是 *单数*请求,而不是所有其他,就好像XMLHttpRequest是一个单例。
function parallelize(bogusUrl, parallelFns) {
for (var i=0, n=parallelFns.length; i<n; i++) {
var fn = parallelFns[i]
,xhr;
try {xhr = new XMLHttpRequest()}
catch (e) {xhr = new ActiveXObject('Microsoft.XMLHTTP')}
xhr.onreadystatechange = function() {
if (xhr.readyState == 1) {
fn();
//xhr.abort();
}
};
xhr.open('GET', bogusUrl);
xhr.send(null);
}
}
parallelize('bogusUrl', [
function(){setInterval(function(){console.log('quarter')}, 250)},
function(){setInterval(function(){console.log('half')}, 500)}
]);
答
块不在JavaScript中创建范围;只有功能。因此,循环的每次迭代都会共享相同的“xhr”变量,并且在每次迭代时都会覆盖它的值。
要解决此问题,您可以创建一个单独的功能做了XHR工作:
function doXHR(fn) {
var xhr = null;
try {xhr = new XMLHttpRequest()}
catch (e) {xhr = new ActiveXObject('Microsoft.XMLHTTP')}
xhr.onreadystatechange = function() {
if (xhr.readyState == 1) {
fn();
//xhr.abort();
}
};
xhr.open('GET', bogusUrl);
xhr.send(null);
}
然后你的循环应该是这样的:
for (var i=0, n=parallelFns.length; i<n; i++)
doXHR(parallelFns[i]);
我想你的建议有轻微改进修改;将“bogusUrl”传递给新函数,并将该函数命名为bogusXHR。但是我仍然得到和以前一样的结果;看到http://jsfiddle.net/a9X7p/也许我还在做错了什么? – 2012-01-11 19:57:19
我不明白那是错的。请注意,当您尝试使用像这样的伪造URL进行XHR呼叫时,它几乎会立即失败。实际上,您正在设置这些间隔定时器,因此XHR调用只运行一次,然后这些定时器处理程序一遍又一遍地被调用。 – Pointy 2012-01-11 20:01:37