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