xhr response with for loop not working

霸气de小男生 提交于 2020-01-05 02:50:10

问题


i have xhr with for loop and it work very rare

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

I'm calling this slike.php. And it work very well, but on responseText, it's not good, sometimes get only last file from loop, sometimes get two file(with same text). I don't know how ti fix it, i was looking everywhere, and can't found the answer.


回答1:


XHR are asynchronous by default, so unless you specify otherwise (async = false in XHR open() method), your loop may have finished before the first XHR may have been initialized.

But the i in your code (this.files[i]) in the loop refers to the same i of your loop, so i may be assigned this.files.length-1 when the first XHR begins. Taht is why you always get only the last file.

That is why you have to create what is called a closure to make sure the index you are using is the one you really want to use.

Try this :

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

Or if would want to really get the files sequentially :

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



回答2:


console.log(xhr.responseText);

You are accessing the current value of xhr (which will usually be the last one created) there instead of the object to which the event handler is attached.

Use this instead of xhr as you did in the previous line.



来源:https://stackoverflow.com/questions/26100329/xhr-response-with-for-loop-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!