I have an array of XMLHttpRequest
(working fine) and I want to know when they are all finished. I wrote the following array of on readystatechange functions:
xhr[i].open('post', 'PHP/write_and_exec_opt.php');
display_opt[i] = xhr[i].onreadystatechange = function(index) {
if (xhr[index].readyState == 4 && xhr[index].status == 200) {
text = xhr[index].responseText.trim();
n_finished++;
console.log('display_opt', n_finished);
}
xhr[index].send(data);
}(i);
The xhr requests are executed properly. But no output on the console log. Why not?
You're really close, but by executing your anonymous function, you end up assigning its return value to the onreadystatechange
property. You never return a value, so you assign undefined
. You probably meant to return a function:
xhr[i].open('post', 'PHP/write_and_exec_opt.php');
display_opt[i] = xhr[i].onreadystatechange = function(index) {
return function() {
if (xhr[index].readyState == 4 && xhr[index].status == 200) {
text = xhr[index].responseText.trim();
n_finished++;
console.log('display_opt', n_finished);
}
};
}(i);
xhr[i].send(data);
That said, it gets confusing fast and there's no good reason to create the temporary function repeatedly, which is why I usually break things out:
Somewhere before (or after, but in any case in the same fundamental scope) your i
loop:
function createStateChangeHandler(index) {
return function() {
if (xhr[index].readyState == 4 && xhr[index].status == 200) {
text = xhr[index].responseText.trim();
n_finished++;
console.log('display_opt', n_finished);
}
};
}
Then in your i
loop:
xhr[i].open('post', 'PHP/write_and_exec_opt.php');
display_opt[i] = xhr[i].onreadystatechange = createStateChangeHandler(i);
xhr[i].send(data);
For what it's worth, I'd suggest looking into using promises for this sort of thing, esp. now that they're a standard part of JavaScript (as of ES2015):
Promise.all(xhrArray.map(function(xhr) {
return new Promise(function(resolve, reject) {
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
resolve(xhr.responseText.trim());
} else {
reject(/*...include some error perhaps...*/);
}
}
};
xhr[index].send(data);
});
})
.then(function(array) {
// `array` contains an array o the results, in the same
// order as `xhrArray`
})
.catch(function() {
// At least one XHR failed
});