-2

I'm using discord.js v12, with the npm module linux-shell-command, run on ubuntu, and have added a feature that pings 3 web domains I manage to see if they're up.

var shellCommand = require("linux-shell-command").shellCommand;
var upDown = [];
if (args == []) {
    // code not written yet
}
else {
    try {
        var domain=['example1.com','example2.com','example3.com'];
        domain.forEach(site=>{
            var sc=shellCommand(`ping -c 1 ${site} |grep '1 received, 0% packet loss'`);
            sc.execute(upDown).then(success => {
                if (success === true) {
                    var packet=sc.stdout;
                    packet=packet.slice(34,-10);
                    if (packet === " 0% packet loss") {
                        upDown.push(`The ${site} website is up!`);
                    }
                }
                else {
                    upDown.push(`The ${site} website is down!`);
                }
            }).catch(e => {
                console.error(e);
            });
        });
    }
    catch (e) {
        console.error(e);
    }
    finally {
        console.log(upDown);
    }
}

if I removed the forEach, I would have to essentially repeat the code block inside it for each domain, without the upDown array, so I tried it this way.

upDown.push() silently fails (nothing is added to the upDown array), no matter how many domains are present.

if I add upDown=upDown.join("\n"); to the finally block, before the console.log(), I get this error for each domain, pointing to the .push() that happens if the domain responds.

undefined
TypeError: upDown.push() is not a function

I'm totally confused, because if I use push right under the declaration of the upDown array, I can push no problem, and if I print upDown to the console just before that push, it sees the array, and it's contents. (verified by manually adding an item to the array declaration)

  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – coagmano Mar 15 '21 at 03:49
  • 1
    `upDown=upDown.join("\n");` sets `upDown` to a string, because `join` returns a string. That's why `push` doesn't work after you change `upDown` – coagmano Mar 15 '21 at 03:50
  • @FredStark it might've, but that page didn't make much sense. I'm still learning JS, and this bot is kinda a crash course. Hope it helps someone else! – jasoncollege24 Mar 15 '21 at 11:20
  • I thought the join was supposed to take place after the push. Maybe my scopes were wrong? – jasoncollege24 Mar 15 '21 at 11:22
  • it looks like `shell-command` is async, which you can tell because you have to call `.then` to get the result. That means that all other code will run before the `then` is called. This is how the `finally` block is called before the `then` block is called. That's why I linked the async call question, it has a great explanation of working with async functions – coagmano Mar 15 '21 at 20:31

1 Answers1

0

I ended up achieving this a somewhat different way. Here's the modified code, which does exactly what I wanted.

var shellCommand = require("linux-shell-command").shellCommand;
if (args == []) {
    //code not written yet
}
else {
    try {
        var domain=['example1.com','example2.com','example3.com'];
        domain.forEach(site =>{
                var result;
                var sc=shellCommand(`ping -c 1 ${site} |grep '1 received. 0% packet loss'`);
                sc.execute().then(success => {
                    if (success === true) {
                        result="up";
                    }
                    else {
                        result="down";
                    }
                    console.log(`${site} is ${result}!`);
                });
        });
    }
    catch (e) {
        console.error(e);
    }
    finally {
        console.log("websites were checked!");
    }
}

This puts the execution, based on the result, right inside the promise, eliminating the need for the extra array, without interrupting the flow.

Thanks for the help! :)