ARH3
ARH3

Reputation: 213

Function isn't passing correct return value from a simple function in nodejs app

I have the following code and am attempting to make a Turntable bot using node.js. this piece of code says when a user types "q+" we have to make sure its not already on the queue, that its not already DJing, and if it meets those 2 requirements, add them to the queue. Otherwise if it doesnt meet one of those first 2 criteria, tell the user and do not touch the queue.

My problem is the "isCurrentDJ(userId)". When I pass a userId through that function, the function gives me the correct answer. However the function ALWAYS passes back "false" even when the answer is "true" and the console.log() function within the isCurrentDJ(userId) function proves so.

I am not the most js-savvy person, so I think this may be a variable scope issue. But I am really not sure and have been struggling with it for hours! Any help would be greatly appreciated. Thanks!

// When someone speaks, listen to see if it is one of the q commands
bot.on('speak', function (data) {
var name = data.name;
var text = data.text;
var userId = data.userid;

// q+ :: Add to Queue
if (text.match(/^q\+$/)) {

  //Index is the position in the queue that this person's name is found.
  //If its not found, -1 is returned.
  var index = queue.indexOf(name);

  //Function to determine if the user is currently a DJ
    function isCurrentDJ(user_id, callback){
      bot.roomInfo(false, function (data) {
        var djList = data.room.metadata.djs;
        for (i = 0; i < djList.length; i++){
          if (djList[i] == user_id){
            console.log('recognized as a DJ'); //Consistently printed!
            callback(true);
          }
        }
        callback(false);
      });
    }


  isCurrentDJ(userId, function(isDJ) {
    //If the user is already in the queue
    if(index > -1){
      //Tell them they are already in there
      bot.speak('You are already on the list');
    } else if(isDJ){
      //Otherwise if they are already a DJ tell them that
      bot.speak('You are already a DJ, '+name);
    }else{
      //Otherise if they are not in the queue add user to end of queue
      queue.push(name);
      //Tell them about it and the updated q
      bot.speak(name+' has been added to queue.');
    }
  });

}

Upvotes: 0

Views: 96

Answers (2)

Laurent Perrin
Laurent Perrin

Reputation: 14881

Your problem is that bot.roomInfo is an asynchronous function.

When you call it, it immediately returns and currDJ is still false. A little while later, the callback (function(data) {...) is called. Most of node.js's API are async so that your code never blocks.

Here's how you should rewrite your code:

// When someone speaks, listen to see if it is one of the q commands
bot.on('speak', function (data) {
   var name = data.name;
   var text = data.text;
   var userId = data.userid;

   // q+ :: Add to Queue
  if (text.match(/^q\+$/)) {

  //Index is the position in the queue that this person's name is found.
  //If its not found, -1 is returned.
  var index = queue.indexOf(name);

  //Function to determine if the user is currently a DJ
    function testCurrentDJ(user_id, cb){

      bot.roomInfo(false, function (data) {
        var djList = data.room.metadata.djs;
        for (i = 0; i < djList.length; i++){
          if (djList[i] == user_id){
            console.log('recognized as a DJ'); //Consistently printed!
            return cb(true);
          }
        }

        cb(false);
      });
    }

  //If the user is already in the queue
  if(index > -1){
    //Tell them they are already in there
    bot.speak('You are already on the list');
    return;
  }

  testCurrentDJ(userId, function(isDJ) {
      //Otherwise if they are already a DJ tell them that
      if(isDJ) {
        bot.speak('You are already a DJ, '+name);
      } else {
       //Otherise if they are not in the queue add user to end of queue
       queue.push(name);
       //Tell them about it and the updated q
       bot.speak(name+' has been added to queue. Is Current DJ? '+isDJ);
  }

    })
}

I've just updated your code to show you the basic idea. In node.js's API, the first argument of callbacks is usually an error object that is null if everything went fine.

Upvotes: 1

Halcyon
Halcyon

Reputation: 57729

Is bot.roomInfo perhaps an asynchronous function? If so the value of currDJ will be set to true, but too late because you've already returned it. You can no operate on the value of currDJ untill that callback is called.

How familiar are you with the concept of asynchronous functions?

Upvotes: 0

Related Questions