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'
}
]
CodePudding user response:
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)
CodePudding user response:
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()