使用异步XMLHttpRequest加载XML文件数组

Rya*_* Li 1 javascript ajax anonymous-function

我想加载一个XML文件数组,并将它们存储在一个数组中.

代码示例:

var src = [ "a", "b", "c", "d" ];
var dest = {};
for (var i in src) {
    var req = new XMLHttpRequest();
    req.open("GET", src[i], true);
    req.onreadystatechange = function(aEvt) {
        if (req.readyState == 4) {
            if (req.status == 200) {
                dump(i + "\n");
                dest[i] = req.responseXML;
            }
        }
    }
    req.send(null);
}
Run Code Online (Sandbox Code Playgroud)

但是,转储结果总是如此

3

3

3

3

它表明i回调中引用的内容始终是外部的i,因此无法正确存储XML文件.

那么,如何解决这个问题呢?我们有大约50个XML文件要加载并逐个加载它们是不可接受的.

谢谢.

Fel*_*ing 5

  1. 不要for..in用于循环数组.使用正常for循环.
  2. 你犯了在循环中创建函数的典型错误.JavaScript没有块作用域,只有函数作用域,因此i在执行您创建的函数时,它总是引用您循环的数组的最后一个元素.他们都具有对参考相同 i.您可以通过使用返回函数的立即执行函数来解决此问题(因此,捕获值i).
  3. 如果你这样做,你还必须捕获一个引用req,否则它将始终引用最后生成的XMLHttpRequest(原因与之相同i).

所以一个解决方案是:

var src = [ "a", "b", "c", "d" ];
var dest = {};
for (var i = src.length;i--;) {
    var req = new XMLHttpRequest();
    req.open("GET", xmlfile, true);
    req.onreadystatechange = (function(i, req) {
        return function(aEvt) {
            if (req.readyState == 4) {
                if (req.status == 200) {
                    dump(i + "\n");
                    dest[i] = req.responseXML;
                }
            }
        };
    }(i, req)); // capturing the current value/reference of i and req
    req.send(null);
}
Run Code Online (Sandbox Code Playgroud)

@Spiny Norman的解决方案可能更具可读性;)