Search code examples
javascriptnode.jsdiscord.jses6-promise

UnhandledPromiseRejectionWarning: DiscordAPIError: Cannot send an empty message


I'm having an issue with sending a message to a Discord channel from a fetch.

I'm fetching Time Series Data from a REST API. I then want to send this data if a Discord user types a command.

Code:

require("dotenv").config();
const fetch = require("node-fetch");
const { Client } = require("discord.js");
const PREFIX = "!";

const getPrice = async (ticker) => {
    let result = "test";
    const request = await fetch(
      `https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=${ticker}&interval=5min&apikey=${process.env.API_KEY}`
    );
    const response = await request.json();
    const data = await response;
    const obj = await data["Time Series (5min)"];
    result = obj[Object.keys(obj)[0]];
    return result;
};

client.on("message", (message) => {
    if (message.author.bot) return;
    if (message.content.startsWith(PREFIX)) {
      const [command, ...args] = message.content
        .trim()
        .substring(PREFIX.length)
        .split(/\s+/);
      const result = getPrice(`${command.toUpperCase()}`);
      message.channel.send(result);
    }
});

I get the following error:

UnhandledPromiseRejectionWarning: DiscordAPIError: Cannot send an empty message

If you take a look at the following code and replace it with a console.log - it works. E.g

Original

message.channel.send(result);

Replace with

console.log(result)

Then it works:

{
  '1. open': '119.0200',
  '2. high': '119.0200',
  '3. low': '119.0200',
  '4. close': '119.0200',
  '5. volume': '302'
}

I suspect it has something to do with Promises, maybe my understanding isn't up to scratch but I've read docs over and over and cannot make sense of it.

I believe the reason that result is empty is because by the time that method is called in the stack, the fetch has not come back with the data, and it attempts to send empty data.

How can I ensure that message.channel.send waits for my fetch to finish before being called?


Solution

  • getPrice is an async function that returns a promise. You need to await the result before you can send it:

    client.on("message", async (message) => {
        if (message.author.bot) return;
        if (message.content.startsWith(PREFIX)) {
          const [command, ...args] = message.content
            .trim()
            .substring(PREFIX.length)
            .split(/\s+/);
          const result = await getPrice(`${command.toUpperCase()}`);
          message.channel.send(result);
        }
    });