Javascript for循环不工作时的xhr响应

Javascript for循环不工作时的xhr响应,javascript,jquery,file,upload,xmlhttprequest,Javascript,Jquery,File,Upload,Xmlhttprequest,我有一个带有for循环的xhr,它的工作非常罕见 for(var i = 0; i < this.files.length; i++) { var xhr = new XMLHttpRequest(); xhr.upload.onprogress = function(e) { }; xhr.onreadystatechange = function(e) { if(this.readyState === 4) {

我有一个带有for循环的xhr,它的工作非常罕见

for(var i = 0; i < this.files.length; i++) {
    var xhr = new XMLHttpRequest();

    xhr.upload.onprogress = function(e) {

    };

    xhr.onreadystatechange = function(e) {
        if(this.readyState === 4) {
            console.log(xhr.responseText);
        }
    };
    var formdata = new FormData();
    formdata.append("files", this.files[i]);
    console.log(this.files[i]);
    xhr.open('POST', 'slike.php');
    xhr.send(formdata);
}

我称之为slike.php。它工作得很好,但在responseText上,它不好,有时只从循环中获取最后一个文件,有时获取两个具有相同文本的文件。我不知道如何修复它,我到处找,找不到答案。

XHR默认是异步的,所以除非在XHR open方法中另外指定async=false,否则在初始化第一个XHR之前,您的循环可能已经完成

但是您代码中的i this.files循环中的[i]引用了您循环中的同一个i,因此当第一个XHR开始时,我可能被指定为this.files.length-1。这就是为什么你总是只得到最后一个文件

这就是为什么您必须创建所谓的闭包,以确保您使用的索引是您真正想要使用的索引

试试这个:

for (var i = 0; i < this.files.length; i++) {
    (function(index, files) { // In this closure : parameters of a function in JS 
                              // are available only in the function,
                              // and cannot be changed from outside of it
        var xhr = new XMLHttpRequest(); // variables declared in a function in JS
                                        // are available only inside the function
                                        // and cannot be changed from outside of it

        xhr.upload.onprogress = function (e) {

        };

        xhr.onreadystatechange = function (e) {
            if (this.readyState === 4) {
                console.log(xhr.responseText);
            }
        };
        var formdata = new FormData();
        formdata.append("files", files[index]); // `index` has nothing to do with `i`, now:
                                                // if `i` changes outside of the function,
                                                //`index` will not
        console.log(files[index]); // Don't keep `console.log()` in production code ;-)
        xhr.open('POST', 'slike.php');
        xhr.send(formdata);
    })(i, this.files)
}
或者如果您真的希望按顺序获取文件:

var i = 0,
    fileNb = this.files.length;

function getNextFile(file) {
    var xhr = new XMLHttpRequest();

    xhr.upload.onprogress = function (e) {

    };

    xhr.onreadystatechange = function (e) {
        if (this.readyState === 4) {
            console.log(xhr.responseText);
            if (++i < fileNb) getNextFile(this.files[i]);
        }
    };
    var formdata = new FormData();
    formdata.append("files", file);
    console.log(file); // Don't keep `console.log()` in production code ;-)
    xhr.open('POST', 'slike.php');
    xhr.send(formdata);
}
getNextFile(i);
您正在访问xhr的当前值,它通常是在那里创建的最后一个值,而不是事件处理程序附加到的对象


用这个代替上一行中的xhr。

可能重复的@Damien duplicate和重复的haha。似乎laruiss复制了答案,但没有修复此特定问题的详细信息。感谢您的回答,我正在发送文件,使用此代码,php返回我错误,并表示文件名为空。这种情况的发生是因为this.files在闭包中具有不同的值。您必须像i.this.files一样传递它,然后作为参数functionindex.files获取它。@laruis它现在可以工作了!,但有一个小问题,毕竟,顺序不一样,这不是一个大问题,但为什么会这样呢?因为XHR在默认情况下是不同步的。为了帮助您理解,这里有一个简单的例子:例如,如果您先下载一个大文件,然后再下载一个小文件,那么您可能会在小文件之后收到一个大文件,尽管您是先请求的。@laruiss感谢您的解释,还有一件事,为什么要在循环中使用函数,该函数会发生什么变化?另一个用户告诉我把这个xhr放在readyState中,你的解决方案和那个有什么不同?谢谢!有了这个,它工作得很好,我很感激:非常感谢。。。我需要这个。。我认为有范围,所以内存引用会不同。。我想不是。感谢您提供此解决方案:
console.log(xhr.responseText);