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

发布于 2024-10-06 10:25:11 字数 700 浏览 7 评论 0原文

我想加载 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);
}

但是,转储结果始终是

3

3

3

3

说明callback中引用的i始终是外层i,导致XML文件无法正确存储。

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

谢谢。

I want to load an array of XML files, and store them in an array.

Code example:

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);
}

However, the dump result is always

3

3

3

3

It shows that the i referenced in callback is always the outer i, so the XML files cannot be stored correctly.

So, how to solve this issue? We have about 50 XML files to load and loading them one by one is not acceptable.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

安穩 2024-10-13 10:25:11
  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);
}

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

  1. Don't use for..in to loop over arrays. Use a normal for loop.
  2. You make the typical mistake of creating a function in a loop. JavaScript has no block scope, only function scope, so i will always refer to the last element of the array you looped over when the functions you created are executed. They all have a reference to the same i. You can solve this by using an immediately executing function that returns a function (thus, capturing the value of i).
  3. If you do this, you also have to capture a reference to req, otherwise it will always refer to the last generated XMLHttpRequest (the same reason as for i).

So one solution would be:

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);
}

@Spiny Norman's solutions might be more readable ;)

无可置疑 2024-10-13 10:25:11

你可以这样做:

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

for (var x = 0; x < src.length; x++) {
    loadXml(x);
}

顺便说一句,你似乎总是加载相同的 xmlfile,但我确信这在你的实际代码中是不同的;)

You could do something like this:

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

for (var x = 0; x < src.length; x++) {
    loadXml(x);
}

By the way, it seems you're always loading the same xmlfile, but I'm sure this is different in your actual code ;)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文