1

I'm creating a discord bot, and trying to structure a bit better.

message.channel.send(require('./commands/' + inputs[0] + '.js')(inputs));

This will require a file and send the returned message to the channel. This is example of a such file:

module.exports = commands => {
let returnM = '';
axios.get(some url).then(response => {
        returnM = response.data.whatever;
    }).catch(error => {
        returnM = "API error.";
    });
}
return returnM;

I get a "cannot display empty message", because the function hasn't returned anything yet, and the message sender is already trying to execute. How can make it so, it waits, till the response is pulled and processed?

EDIT: Got IT! Thanks for the help! Made the exported function async and the whole axios pull return await, and the handler, look like this:

require('./commands' + inputs[0] + '.js')(inputs).then(m => message.channel.send(m));
9349u8u3guhir
  • 13
  • 1
  • 4
  • 1
    Does `channel.send()` accept a promise as parameter? – Sirko Feb 10 '18 at 11:21
  • @Sirko I don't think so. – 9349u8u3guhir Feb 10 '18 at 11:28
  • The short answer is: functions that cannot return a result synchronously do not return a result at all, at least not directly. They return a Promise, and the Promise returns the result when it's ready. You use ```then()``` to attach a callback to a Promise and do things with its result when it's ready. – Aurast Feb 10 '18 at 12:01

2 Answers2

0

The simplest way would be to use ES7 Async Await...

module.exports = async commands => {
  return await axios.get(some url).then(response => {
    return response.data.whatever;
  }).catch(error => {
    return "API error.";
  });
}

You need to add the async keyword just before the function declaration, and the await keyword before the call you want to wait on. This way whenever you prefix a function call with the await keyword the async function will pause and wait for the called function to return. This allows you to write async code in a synchronously fashion.

Alternatively, you could use a Promise but that would require more changes to your message channel code.

Jon Miles
  • 9,605
  • 11
  • 46
  • 66
0

Your exported command file will fail to execute since the return returnM; is outside of the function

Try this:

// export a function that when called returns
// a promise that resolves to `whatever`

module.exports = commands => axios.get(url).then(
  response => response.data.whatever,
  error => 'API error.'
)

.

// when required, called and then resolved,
// calls the send command with the resolved value `whatever`
require('./commands/' + inputs[0] + '.js')(inputs).then(message.channel.send)

beware if someones trys to call a ../index command or something

Endless
  • 34,080
  • 13
  • 108
  • 131
  • So I made this change: `axios.get(url).then(response => {return 1});`, but how do I obtain this value on the other side (with the second `.then`)? – 9349u8u3guhir Feb 10 '18 at 11:43