为什么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]); 
+0

我想你的建议有轻微改进修改;将“bogusUrl”传递给新函数,并将该函数命名为bogusXHR。但是我仍然得到和以前一样的结果;看到http://jsfiddle.net/a9X7p/也许我还在做错了什么? – 2012-01-11 19:57:19

+0

我不明白那是错的。请注意,当您尝试使用像这样的伪造URL进行XHR呼叫时,它几乎会立即失败。实际上,您正在设置这些间隔定时器,因此XHR调用只运行一次,然后这些定时器处理程序一遍又一遍地被调用。 – Pointy 2012-01-11 20:01:37