Search code examples
javascriptasynchronousdiscord.jsunirest

How to return unicode response using callback


I have been having trouble with retrieving the results of a query to an API back to a variable. I am trying to use a callback function but it is not working as expected.

My problem is that I am getting a response back from the API and I can see it outputted to the console when I log it, but it is still not being set to a variable, causing the variable to be undefined.

Here is the function making the query and its respective callback function

function getResult(result)
{
    let gameInfo = result;
    //console.log(gameInfo); /// When uncommented, the response can be seen here, so I know my callback is getting the result.
    return gameInfo;
}
function queryRAWGDatabase(callback,title)
{
    title = title.split(' ').join('-');
    var req = unirest("GET", "https://rawg-video-games-database.p.rapidapi.com/games/" + title);

    req.headers({
        "x-rapidapi-key": process.env.RAWG_GAME_DATABASE_KEY,
        "x-rapidapi-host": "rawg-video-games-database.p.rapidapi.com",
        "useQueryString": true
    });
    req.end(function (result) {
        if (result.error)
        {
            return null;
        };
        return callback(result.body);
    });
}

And here is where I am calling the function and trying to set it to a variable.

async function embedBuilder(message)
{
    await message.author.send("Lets get to work!\nPlease enter the title of your event. (Must be shorter than 200 characters)");
    const title = await collector(message,200);
    message.author.send("Please enter the name of the game. (Must be shorter than 200 characters)\nEnter \"None\" if this event does not have a game. ");
    const game_title = await collector(message,200,true);
    let game = queryRAWGDatabase(getResult,game_title); ////////////// CALL MADE HERE /////////
    message.author.send("Please enter a short description of your event. (Must be shorter than 2000 characters)\nEnter \"None\" if no. ");
    const description = await collector(message,2000,true);
    console.log(game); //// When I print it here, I get undefined!
    if (description != null)
    {
        var eventEmbed = new Discord.MessageEmbed()
        .setColor('RANDOM')
        .setTitle(title)
        .setAuthor(message.author.username)
        .setDescription(description)
        .addField("Participants", "None")
        .addField("Not Attending", "None")
        .addField("Tentative", "None")
        .setImage(game.background_image);
    }
    else // Build embed without description
    {
        var eventEmbed = new Discord.MessageEmbed()
        .setColor('RANDOM')
        .setTitle(title)
        .setAuthor(message.author.username)
        .addField("Participants", "None")
        .addField("Not Attending", "None")
        .addField("Tentative", "None")
        .setImage(game.background_image);
    }
/// . . .

Finally, here are my errors.

(node:22974) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'background_image' of undefined
    at embedBuilder (/home/caleb/Programming/PlannerBot/commands/plan.js:80:24)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:22974) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:22974) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Solution

  • First of all, you need to await queryRAWGDatabase function:

    let game = await queryRAWGDatabase(game_title)
    

    You don't need to have a callback if you await, so I removed getResult

    However, at the moment this function is not await'able. To solve that, we need to edit that function so it would return a return Promise instance. It accepts callback with resolve & reject arguments. And you can call resolve to resolve the promise:

    function queryRAWGDatabase(title) {
        return new Promise((resolve, reject) => {
            title = title.split(' ').join('-');
            var req = unirest("GET", "https://rawg-video-games-database.p.rapidapi.com/games/" + title);
    
            req.headers({
                "x-rapidapi-key": process.env.RAWG_GAME_DATABASE_KEY,
                "x-rapidapi-host": "rawg-video-games-database.p.rapidapi.com",
                "useQueryString": true
            });
            req.end(function (result) {
                if (result.error) {
                    reject('Error: ' + result.error);
                    return;
                };
                resolve(result.body);
            });
        })
    }
    

    Instead of the callback, you need to call resolve. Regarding result.error, you can call reject, and then you will get an exception when awaiting.