Jem
Jem

Reputation: 769

Return array from function nested within a function and handle promise check

I'm working on a Discord bot using node.js. The idea is fairly simple, the bot checks chat messages for certain phrases that trigger it to do various actions. Mostly related to giving info about various game servers.

I've got the bot working and it does the basics of what I wanted it to do.

I'm looking to expand its functionality a bit however.

Basically when people type in a certain term like 'server 1v1' the bot will give the connection info to that server as well as query the current state of the server.

I'm using an npm package called gamedig to do this.

The code is as follows

//Query Minecraft Server
var serverInfo = function(chatTrigger){

//create an array of servers
//Name of the array arrays within the array is the chat trigger, the first value of each chat trigger array is the query mode for gamedir, second value is the IP or server query URL.
var namedServerArrays = {
    '1v1' : ["csgo","192.168.1.1",2016],
    '10man' : ["csgo","192.168.1.2",27017],
    'minecraft' : ["minecraft","192.168.1.3",2018]
}

//Convert named array data based on the chat triggers to a variable.
//This doesn't have to be done but gamedig gets a little pissy sometimes if you feed it straight arrays. No idea why.
var gameType = namedServerArrays[chatTrigger][0];
var gameHost = namedServerArrays[chatTrigger][1];
var gamePort = namedServerArrays[chatTrigger][2];

//Query server based on chatTrigger input.
Gamedig.query({
        type: gameType,
        host: gameHost,
        port: gamePort
    },
function(e,state) {
        if(e){
            console.log("Server is offline");
            return "Server connection error.";
        }else{
            var playersOnline = state.players.length;
            var currentMap = state.map;

                //Vomit a bunch of error checking.
                console.log("The " + chatTrigger + " server is online.");
                console.log("Players Online: " + playersOnline);
                console.log("Server map: " + currentMap);
                console.log("User was given " + chatTrigger +" server connection information.");

                return [playersOnline,currentMap];
        }
});
//End Query 

var queryReturnState = Gamedig.query();}

What my hung up is how do I return the data from the gamedig query function back to the serverInfo function so that it can then be returned by the serverInfo function to whatever is using the serverInfo function?

In its current state the console logs all the relevant data up to date and correctly but will eventually encounter a UnhandledPromiseRejectionWarming.

(node:1479) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Cannot set property 'callback' of undefined (node:1479) 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.

I'm having a bit of trouble understanding how to handle promises in node.js as well.

Any help towards me getting this to work and understand better is appreciated.

Upvotes: 0

Views: 606

Answers (2)

Para
Para

Reputation: 53

This was likely caused by the var queryReturnState = Gamedig.query(); at the bottom of your snippet.

According to the API, Gamedig.query requires at least one parameter. Since the parameter was missing, it was likely trying to set callback on that non-existent object.

Upvotes: 0

Matt
Matt

Reputation: 74630

That looks like a bug in the underlying library or an issue with the use of the library. Try using the the promise API which will at least catch the error, and possibly avoid using callbacks in the underlying gamedig library.

When using a promise API, all you need to do is return a value or the promise of a value from your functions.

Wherever you call serverInfo() use a .then to handle the asynchronous promise result and then send it to the chat, whatever that may be.

serverInfo(blah).then(function(result){
   chat.send(result)
})

Promised code

// Query Minecraft Server
var serverInfo = function(chatTrigger){
  var namedServerArrays = {
    '1v1' : ["csgo","192.168.1.1",2016],
    '10man' : ["csgo","192.168.1.2",27017],
    'minecraft' : ["minecraft","192.168.1.3",2018]
  }

  // Convert named array data based on the chat triggers to a variable.
  // This doesn't have to be done but gamedig gets a little pissy sometimes if you feed it straight arrays. No idea why.
  var gameType = namedServerArrays[chatTrigger][0];
  var gameHost = namedServerArrays[chatTrigger][1];
  var gamePort = namedServerArrays[chatTrigger][2];

  //Query server based on chatTrigger input.
  return Gamedig.query({
        type: gameType,
        host: gameHost,
        port: gamePort
    })
    .then(function(state){
        var playersOnline = state.players.length;
        var currentMap = state.map;

        //Vomit a bunch of error checking.
        console.log("The " + chatTrigger + " server is online.");
        console.log("Players Online: " + playersOnline);
        console.log("Server map: " + currentMap);
        console.log("User was given " + chatTrigger +" server connection information.");

        return [playersOnline,currentMap];
    })
    .catch(function(error){
        console.error(error);
        return 'Server connection error';
    });
}

Upvotes: 1

Related Questions