问题
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