Reputation: 11
I'm trying to write a small program that will ping internal addresses to check if a server is down. The problem is that I cant get the timing right. If I put a console.log() inside the for of loop it returns the objects I want but several times of cource. If I write a console.log after the for of loop, I only get an empty array, probably because the loop is not finished yet.I have tried to fix this in various ways but keep running into problems. I use node-cmd to send an http ping as normal pings only work against domains.
You can ignore my nightmare regex :) It should just split the response into an array which is then pushed to object
var cmd = require('node-cmd');
const hosts = [
'https://adressone.com',
'https://adresstwo.com',
'https://adressthree.com',
'https://adressfour.com'
];
let results = [];
for (let host of hosts) {
cmd.run(`http-ping.exe ${host}`,
async function(err, data, stderr) {
const result = await data.split('>');
const resultDig = result[1].replace(/[^0-9\.]+/g, " ").replace(/2$/g, "").trim().split(' ')
results.push({
host: host,
status: resultDig[0],
bytes: resultDig[1],
time: resultDig[2],
});
}
);
}
console.log(results);
The result I would like in console.log(results):
[{
host: 'https://adressone.com',
status: '200',
bytes: '703',
time: '640'
},
{
host: 'https://adresstwo.com',
status: '200',
bytes: '703',
time: '640'
},
{
host: 'https://adressthree.com',
status: '200',
bytes: '703',
time: '640'
},
{
host: 'https://adressfour.com',
status: '200',
bytes: '703',
time: '640'
}
]
Upvotes: 1
Views: 591
Reputation: 20006
The best approach for this question will be by using Promise
s in JavaScript.
An example for this implementation.
async function parseResult() {
const hosts = [
"https://adressone.com",
"https://adresstwo.com",
"https://adressthree.com",
"https://adressfour.com",
];
const promises = [];
for (let host of hosts) {
const response = new Promise(function (resolve, reject) {
setInterval(async () => {
resolve({
status: "Success",
});
}, 1000);
});
promises.push(response);
}
const finalResult = await Promise.all(promises);
return finalResult;
}
parseResult().then((res) => console.log(res));
OR
async function parseResult() {
const hosts = [
"https://adressone.com",
"https://adresstwo.com",
"https://adressthree.com",
"https://adressfour.com",
];
const promises = hosts.map(
(host) =>
new Promise(function (resolve, reject) {
setInterval(async () => {
resolve({
status: "Success",
});
}, 1000);
})
);
const finalResult = await Promise.all(promises);
return finalResult;
}
parseResult().then((res) => console.log(res));
A Pseudo code for your question will be like below
var cmd = require("node-cmd");
async function parseResult() {
const hosts = [
"https://adressone.com",
"https://adresstwo.com",
"https://adressthree.com",
"https://adressfour.com",
];
let promises = [];
for (let host of hosts) {
const response = cmd.run(
`http-ping.exe ${host}`,
async function (err, data, stderr) {
const result = await data.split(">");
const resultDig = result[1]
.replace(/[^0-9\.]+/g, " ")
.replace(/2$/g, "")
.trim()
.split(" ");
// Returning a promise here
return new Promise(function (resolve, reject) {
resolve({
host: host,
status: resultDig[0],
bytes: resultDig[1],
time: resultDig[2],
});
});
}
);
promises.push(response);
}
// promises array will hold a list of promises now
// Await till all the promises are resolved and that will be your final result
const finalResult = await Promise.all(promises);
return finalResult;
}
parseResult().then((res) => console.log(res));
Explanation: Here the parseResult
function loops through an array hosts
and will run an async operation against each nodes in hosts
array. The result of this operation is a Promise
, so your final promises
array will be holding a list of promises. Once all this promises are resolved, you will get your final result. You can detect when all your promises are resolved by using await Promise.all(promises)
Upvotes: 1
Reputation: 4924
I'd suggest to use node-cmd-promise
. I removed the splitting:
const cmd = require('node-cmd-promise')
const hosts = [
'https://adressone.com',
'https://adresstwo.com',
'https://adressthree.com',
'https://adressfour.com',
]
async function main() {
const results = []
for (const host of hosts) {
const result = await cmd(`echo ${host}`)
// Insert logic here
const resultDig = [result.stdout, 'foo', 'bar']
results.push({
host,
status: resultDig[0],
bytes: resultDig[1],
time: resultDig[2],
})
}
console.log(results)
}
main()
Upvotes: 0