1

I'm having trouble grappling with variable scope withing a Node.js application I'm making, generally I understand how variable scope works in/around a function (in this instance, anonymous callback functions).

What I'm battling with is what is the best way of maintaining vairables through a chain/hole of anonymous callbacks. Where as normally I could pass the variables to the functions, but because I'm using mongoose (mongodb ORM) I cant pass my own variables in. and so have to either resort to defining the variables over and over at each step deeper into the callback.

What is the best way of doing this?

Below is my code where I end up getting variables undefined by the time I want to use them for tweeting:

var userBid = tag.user;

User.find({id: userAid}, function(err, userA){

  if (err) {console.log("Error getting user A for tweeting ", err)}
  else {
    var userAName = userA.twitter.screenName;
    var userBid2 = userBid;
    User.find({id: userBid2}, function(err, userB){

      if (err) {console.log("Error getting user B for tweeting ", err)}
      else {

        var action = "@"+ userAName + " just claimed some of @" + userB.twitter.screenName + " 's turf as their own.";

        twitterClient.updateStatus(action, function(err, resp){
          if (!err) {
            console.log("Tweeted: ", action );
          } else {
            console.log("TwitBot error:", err);
          }
        });
      }
    });
  }
 });

Surely there is a better way of handling this... ANy help is much appreciated.

3
  • 1
    This is not PHP/C/Java! You don't have to pass around your variables. They'll always be available through the scope lookup chain... Just declare them once at the top level of your scope (as you have it now), and you can then access them from inside those functions. No need to pass them down the rabbit hole!! Commented Sep 1, 2011 at 18:46
  • Um... if this were the case, then why were my variables undefined? And what would be the reason for bind/currying see @Raynos' answer below Commented Sep 2, 2011 at 9:47
  • Better late than never: Your userBid is defined correctly and should be accessible inside of your query. It is defined outside of your function and thus will be visible inside of your function below. Just make sure that the variable is actually defined correctly and that tag.user is not undefined. A simple console.log(userBid) should solve that question. Commented Feb 12, 2018 at 13:13

1 Answer 1

2
User.find({
    id: userAid
}, function(err, userA) {
    if (err) throw err;
    else {
        User.find({
            id: tag.user
        }, (function(userAName, err, userB) {
            if (err) throw err;
            else {
                var action = "@" + userAName + " just claimed some of @" + userB.twitter.screenName + " 's turf as their own.";
                twitterClient.updateStatus(action, function(err, resp) {
                    if (!err) {
                        console.log("Tweeted: ", action);
                    } else {
                        console.log("TwitBot error:", err);
                    }
                });
            }
        }).bind(null, userA.twitter.screenName));
    }
});

Either use closure scope (tag.user is available through closures) or use .bind to bind variables to a function.

For example we've curried the userAName variable into the anonymous function by doing

(function(userAName, normal, arguments, here) {

}).bind(null, userAName));
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer, I'm confused about this section: (function(userAName, err, userB) { I'm worried that seeing as this callback is being fired by a third party (mongoose) , I cant just inters userAName in, I was under the impression that the 1st argument is err ... Or is it safe to do what you've suggested?
@Christopher that's how .bind works. It returns a new function with the first argument locked and slots the rest of the arguments after the first argument

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.