Search code examples
javascriptnode.jsasync-awaitdiscorddiscord.js

How to make discord wait for the script to finish running and how to not reply to discord before getting the data needed?


I'm new to node.js and async programming so I'm a bit confused on why this is happening. I am trying to run a discord bot which will give me data from a 3rd party website. I am able to query the data from the 3rd party site and I can see the data in my console. However the data is not able to show up in discord.

const { SlashCommandBuilder } = require('@discordjs/builders');
const execFile = require('child_process').execFile;
const path = require('node:path');
const commandsPath = path.join(__dirname, '..', 'Folder_name');
let scriptPath = path.join(commandsPath, 'querydata.js');
let output = "";

module.exports = {
    data: new SlashCommandBuilder()
        .setName('cmdname')
        .setDescription('blank'),
    async execute(interaction) {
        await runScript(scriptPath)
        await interaction.reply(output)
    },
};

function runScript(scriptPath) {
    return new Promise((resolve, reject) => {
        execFile('node', [scriptPath], (error, stdout, stderr) => {
            if (error) {
                console.error('stderr', stderr);
                throw error;
            }
            console.log(stdout);
            output = stdout
            resolve(output)
        });
    });
}

I have tried using Promise, async/await but I would either see this error

RangeError [MESSAGE_CONTENT_TYPE]: Message content must be a non-empty string.

Changing my code to the code below I would get this error instead, where I am able to query the data but by the time I gotten the data discord would terminate the call, thinking that my bot did not respond. (The bot is online when I tested this) enter image description here

module.exports = {
    data: new SlashCommandBuilder()
        .setName('cmd')
        .setDescription('blank'),
    async execute(interaction) {
        runScript(scriptPath)
            .then(interaction.reply(output))
    },
};

function runScript(scriptPath) {
    return new Promise((resolve, reject) => {
        execFile('node', [scriptPath], (error, stdout, stderr) => {
            if (error) {
                console.error('stderr', stderr);
                throw error;
            }
            console.log(stdout);
            output = stdout
            resolve(output)
        });
    });
}

I do not get it, I thought if I used await then the script would wait until the runScript function finishes before replying to discord. But the script keeps trying to send the empty output string to discord which causes the RangeError error. On the other hand, when I use the second code block, I get the error in Discord(the error seen in the pic).


Solution

  • this should work for ya!

    async execute(interaction) {
      await runScript(scriptPath)
        .then(output => interaction.reply(output))
    }
    

    it will await the script which literally means to wait for it to finish it's promises, then will grab the output from that and reply with it.