You cannot execute multiple http requests in a for...loop
cycle without waiting for a response.
To write this code in a modern way you need some new construct/pattern, like Promise
. You can then wait for each response, collect responses, and exit to the caller.
To make an example, look at my solution for a javascript client. This will work with a small effort in Node.js
too, you just have the change the way to do the request in the block function ExecutionBlock
.
Supposed that we have an array of parameters we want to send to some urls / or and array of different urls, we will run then using a Promise.all
construct.
Try it out in the following snippet.
To see how apply this solution to Node.js
see my implementation of http
get and post here and see later in this post a for more complex execution in node of asynchronous tasks.
var console = {
log: function(s) {
document.getElementById("console").innerHTML += s + "<br/>"
}
}
// Simple XMLHttpRequest
// based on https://davidwalsh.name/xmlhttprequest
SimpleRequest = {
call: function(what, response) {
var request;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
request = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
request = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {}
}
}
// state changes
request.onreadystatechange = function() {
if (request.readyState === 4) { // done
if (request.status === 200) { // complete
response(request.responseText)
} else response();
}
}
request.open('GET', what, true);
request.send(null);
}
}
//PromiseAll
var promiseAll = function(items, block) {
var self = this;
var promises = [],
index = 0;
items.forEach(function(item) {
promises.push(function(item, i) {
return new Promise(function(resolve, reject) {
if (block) {
block.apply(this, [item, index, resolve, reject]);
}
});
}(item, ++index))
});
return Promise.all(promises)
}; //promiseAll
// LP: deferred execution block
var ExecutionBlock = function(item, index, resolve, reject) {
SimpleRequest.call('https://icanhazip.com/', function(result) {
if (result) {
console.log("Response[" + index + "] " + result);
resolve(result);
} else {
reject(new Error("call error"));
}
})
}
arr = [1, 2, 3]
promiseAll(arr, (item, index, resolve, reject) => {
console.log("Making request [" + index + "]")
ExecutionBlock(item, index, resolve, reject);
})
.then((results) => { console.log(results) })
.catch((error) => { console.error(error) });
<div id="console" />
For a similar approach through Promise
and Promise.all
applied to node.js see my question here. that is about spawn the execution of generic processes in node in a async way.
A more complex example here shows how is possible to spawn and chain more than one level of http calls execution in a N * M
http.get
executors using Promise
. So you will star executing N
requests, each of them will start M
requests, and thanks to Promise.all
you will wait each of them, wait all results for the first M
and then all results for the N * M
array of requests responses.