Rectangle 27 0

Named functions will be executed within the same scope that the anonymous functions are and would have access to all of variables you are currently using. This approach would make your code less nested and more readable (which is good) but would still technically be in "callback hell". The best way to avoid situations like this is to wrap your asynchronous libraries (assuming they don't already provide promises) with a promise library like Q. IMO, promises provide a much more clear picture of the execution path.

You can avoid the predicament of not knowing where variables came from by binding parameters to your named function using bind, for instance:

function handleRequest(res, err, text, url) {
    if (err) {
        res.status(HttpStatus.INTERNAL_SERVER_ERROR).send(err);
        return;
    }
    var newMongooseModel = new AnotherMongooseModel();
    newMongooseModel.id = id;

    newMongooseModel.save(function (err) {
        if (err) {
            res.status(HttpStatus.INTERNAL_SERVER_ERROR).send(err);
        } else {
            res.send({url: url, text: text});
        }
    });
}

...
generateUrl(Id, handleRequest.bind(null, res));

My concern with named functions is that, even though they can access the same variables, it's not clear when reading those functions where those variables are coming from.

javascript - Avoiding callback hell in nodeJs / Passing variables to i...

javascript node.js express callback mongoose
Rectangle 27 0

Either one in small amounts is fine, but together they make code rigid and unmaintainable. The solution to avoiding callback hell is to avoid these two things by:

  • Naming your functions and pulling them out of function calls.
function check_auth_user(username, password, done) {

    // Make a new client and open the connection.
    function connect(callback) {
        var client = new pg.Client("pg://user:pass@127.0.0.1/database");

        client.connect(function (err) {
            if (err) {
                console.error('could not connect to postgres', err);
                return callback(err);
            }

            callback(null, client);
        });
    }

    // Query the database.
    function query(callback, results) {
        var client = results.client;
        var q = 'select * from "user" where username = $1 and password = $2';
        var params = [username, password];

        client.query(q, params, function (err, result) {
            if (err) {
                console.error('error running query', err.stack || err.message);
                return callback(err);
            }

            callback(null, result);
        });
    }

    // Do stuff with the result of the query.
    function handleQueryResult(callback, results) {
        var result = results.query;

        if (result.rowCount === 0) {
            return callback();
        }

        var row = result.rows[0];

        console.log(row);

        passport.serializeUser(function(res, done) {
            done(null, res);
        });

        passport.deserializeUser(function(user, done) {
            done(null, res);
        }); 

        callback(null, row);
    }

    // Let async handle the order. Allows remixing.
    async.auto({
        connect: [connect],
        query: ['connect', query],
        row: ['query', handleQueryResult]
    }, function (err, results) {
        if (err) {
            return done(err);
        }

        // Callback with the row.
        done(null, results.row);
    });
}

I've used async.auto here, even if async.waterfall would do. The reasoning behind that is that it's difficult to move, add or remove steps in a waterfall, and that's been a source of bugs. The auto lets you add steps without worrying and the order/parallelism is handled by async.

This is obviously using a lot more vertical space, but I think that's a small price to pay for the modularity.

Node.js/Async - How to avoid callback hell with async? - Stack Overflo...

node.js node-async
Rectangle 27 0

async function() {
  const userDetail = await User.getUserDetail(req.user.id);

  if (req.user.entity_id != '-1') {
    // you can batch the two into simulatenous queries (see below)
    const entityPrimary = await Entity.getEntityPrimary(req.user.entity_id);
    const entityPayment = await Entity.getEntityPayment(req.user.entity_id);

    if (entityPayment.length > 0) {
      const isSubscribed = await Entity.subscriptionInfo(entityPayment[0]['date'], entityPayment[0]['exp_date']);
      res.render('capitol', {
        user: req.user,
        title: 'MCIC',
        user_detail: userDetail,
        entity_primary: entityPrimary,
        entity_payment: entityPayment,
        subscriber: true,
        is_subscribed: isSubscribed
      });
    } else {
      res.render('capitol', {
        user: req.user,
        title: 'MCIC',
        user_detail: userDetail,
        entity_primary: entityPrimary,
        entity_payment: entityPayment,
        subscriber: false
      });
    }
  } else {
    res.render('capitol', {
      user: req.user,
      title: 'MCIC',
      user_detail: userDetail
    });
  }
}

I use this pattern. I'm using Babel but there are other options for getting async await support. I happen to be using PostgreSQL with pg-promise and my simultaneous queries would look like this:

const results = await db.tx(t => t.batch([query1, query2]));

Corrected the pg-promise code example ;)

javascript - How to avoid callback hell in this scenario? - Stack Over...

javascript node.js asynchronous callback
Rectangle 27 0

you can remove the callback hell using async / await like this

const Promise = require('bluebird');
const User = Promise.promisifyAll(require('PATH_TO_USER'));
const Entity = Promise.promisifyAll(require('PATH_TO_ENTITY'));

async function yourController(req, res, next) {
  try {
    const userDetail = await User.getUserDetail(req.user.id);
    if(req.user.entity_id !== -1) {
      const entityPrimary = await Entity.getEntityPrimary(req.user.entity_id);
      const entityPayment = await Entity.getEntityPayment(req.user.entity_id);

      if(entityPayment.length > 0) {
        const isSubscribed = await Entity.subscriptionInfo(entityPayment[0]['date'], entityPayment[0]['exp_date']);
        return res.render('capitol', {
          user: req.user,
          title: 'MCIC',
          user_detail: userDetail,
          entity_primary: entityPrimary,
          entity_payment: entityPayment,
          subscriber: true,
          is_subscribed: isSubscribed
        })
      } else {
          return res.render('capitol', {
            user: req.user,
            title: 'MCIC',
            user_detail: userDetail,
            entity_primary: entityPrimary,
            entity_payment: entityPayment,
            subscriber: false
          })
      }
    } else {
        return res.render('capitol', {
          user: req.user,
          title: 'MCIC',
          user_detail: userDetail
        })
    }
  } catch(e) {
    // handle exception here
  }
}

the steps are

async
async function yourController(req, res, next)
bluebird
await

javascript - How to avoid callback hell in this scenario? - Stack Over...

javascript node.js asynchronous callback
Rectangle 27 0

Sequelize 2.0 ships with native promises, so you don't need to require a promise lib manually in your code. With 2.0 your snippet can be written as:

db.Role.findAll().bind({}).then(function(roles) {
  this.roles = roles;

  return db.User.findAll({where: {permission: 'coach'}});
}).then(function(coaches) {
  res.render('users/edit_profile', {successFlash: successFlash, user: user, roles: this.roles, coaches: coaches});
}).catch(function(errors) {
  console.log("Error", errors);
  res.render('dashboard', {successFlash: successFlash, errors: errors});
});

You only need a single catch block, because any error is propagated to the top of the chain when you return a promise.

The bind({}) part makes an empty object available inside all functions in your promise chain so you can pass context along in that way. If could also do bind(this), if you want to be able to access something from the outer context, without having to do the idiomatic var self = this

node.js - How to avoid callback hell in nodejs for sequelize - Stack O...

node.js callback sequelize.js
Rectangle 27 0

get_user: function(req, res) {
    var users = null;
    func.get_users(function(result){
      if (result==null) //handle error
      res.render('users/get_users', {users: users});
   });
}

get_users: function(callback) {
        db.User.findAll().success(function(users){
            callback(users);
        }).error(function(err){
            callback(null);
        });
    }

Thanks. This works! From the first code snippet which I have posted, suppose I want to fetch all roles first, and then users, how can I refactor the code?

node.js - How to avoid callback hell in nodejs for sequelize - Stack O...

node.js callback sequelize.js
Rectangle 27 0

step1(function (value1) {
    step2(value1, function(value2) {
        step3(value2, function(value3) {
            step4(value3, function(value4) {
                // Do something with value4
            });
        });
    });
});
Q.fcall(promisedStep1)
.then(promisedStep2)
.then(promisedStep3)
.then(promisedStep4)
.then(function (value4) {
    // Do something with value4
})
.catch(function (error) {
    // Handle any error from all above steps
})

This is nice. Note also, that you don't need to use Q library here, the vanilla javascript Promise suffices.

Sign up for our newsletter and get our top new questions delivered to your inbox (see an example).

javascript - How to avoid callback hell in this scenario? - Stack Over...

javascript node.js asynchronous callback
Rectangle 27 0

I believe you should first go through the concepts of callback functions and how to avoid callback hell Below links would help you kick start with callbacks

node.js - NodeJS MongoDB Callback Hell - Stack Overflow

node.js mongodb callback
Rectangle 27 0

I understand that I can replace my anonymous functions with names functions, but then I would need to pass arounds variables. How would my inner function access res for instance if the function is defined elsewhere?

function x (a) {
    do_something(function(){
        process(a);
    });
}
function x (a) {
    do_something(y_maker(a)); // notice we're calling y_maker,
                              // not passing it in as callback
}

function y_maker (b) {
    return function () {
        process(b);
    };
}

In the code above, y_maker is a function that generates a function (let's call that function's purpose "y"). In my own code, I use the naming convention .._maker or generate_.. to denote that I'm calling a function factory. But that's just me and the convention is in no way standard or widely adopted in the wild.

exports.generateUrl = function (req, res) {
    var id = req.query.someParameter;

    var query = MyMongooseModel.findOne({'id': id});
    query.exec(make_queryHandler(req,res));
};

function make_queryHandler (req, res) {
    return function (err, mongooseModel) {
        if(err) {
            //deal with it
        }
        else if (!mongooseModel) {
            generateUrl(Id,make_urlGeneratorHandler(req,res));
        } else {
            //deal with already exists
        }
}}

function make_urlGeneratorHandler (req, res) {
    return function (err, text, url) {
        if (err) {
            res.status(HttpStatus.INTERNAL_SERVER_ERROR).send(err);
            return;
        }
        var newMongooseModel = new AnotherMongooseModel();
        newMongooseModel.id = id;
        newMongooseModel.save(make_modelSaveHandler(req,res));
}}

function make_modelSaveHandler (req, res) {
    return function (err) {
        if (err) res.status(HttpStatus.INTERNAL_SERVER_ERROR).send(err);
        else res.send({url: url, text: text});
}}

This flattens out the nested callbacks. As an additional benefit, you get to properly name what the function is supposed to do. Which I consider good practice.

It also has the added advantage that it is significantly faster than when using anonymous callback (either with nesting callbacks or with promises, though if you pass named functions to promise.then() instead of anonymous functions then you'll get the same speed up benefits). A previous SO question (my google-fu is failing me today) found that named functions are more than twice the speed (if I remember correctly it was more than 5 times faster) of anonymous functions in node.js.

While this question got really good answers, I chose this answer because I think it leads to the cleanest code. It is immediately clear where variables are coming from and it is very flat. Thanks!

This looks like a good solution to avoid callback hell. Are there any arguments against using this, or any disadvantages?

Sign up for our newsletter and get our top new questions delivered to your inbox (see an example).

javascript - Avoiding callback hell in nodeJs / Passing variables to i...

javascript node.js express callback mongoose
Rectangle 27 0

To get some fast rewards, you can extract the callback functions as named functions that lie on your module level:

// Before: Deeply nested

asyncOperationA(function(resA) {
  asyncOperationB(resA, function(resB) {
    asyncOperationC(resB, function(resC) {
      console.log(resC)
    })
  })
})


// After: flattened

function handleA(resA) {
  asyncOperationB(handleB)
}

function handleB(resB) {
  asyncOperationC(handleC)
}

function handleC(resC) {
  console.log(resC)
}

asyncOperationA(handleA)

Better option is to modify your code to use promises. And greatest readiblity is gained using async/await keywords. To use async/await you need to have quite recent Node version or use a transpiler that transforms those to vanilla JavaScript.

javascript - How to avoid callback hell in this scenario? - Stack Over...

javascript node.js asynchronous callback
Rectangle 27 0

Use promises. Using Q and mongoose-q it would give: something like that:

exports.generateUrl = function (req, res) {
    var id = req.query.someParameter;
    var text = "";

    var query = MyMongooseModel.findOne({'id': id});
    query.execQ().then(function (mongooseModel) {

        if (!mongooseModel) {
            return generateUrl(Id)

     }).then(function (text) {
       var newMongooseModel = new AnotherMongooseModel();
       newMongooseModel.id = id;
       text = text;

       newMongooseModel.saveQ()
     }).then(function (url) {
        res.send({url: url, text: text});
     }).fail(function(err) {
        res.status(HttpStatus.INTERNAL_SERVER_ERROR).send(err);
     });
};

Oh, and if I need to make another Mongoose query in a then, then I'm still "stuck" with an additional function nesting. (Edit: removed question about cascading variables between functions)

Then yo have to create a var in the generateUrl scope. See updated answer with var text

javascript - Avoiding callback hell in nodeJs / Passing variables to i...

javascript node.js express callback mongoose
Rectangle 27 0

Here is the code modified to use async whenever needed.

Obviously, it does not make the code any more readable. I would suggest additional changes:

  • Querying the database should be separated in its own method (it is indeed a model method), thus allowing error checking to happen in its own "dominion".
  • Passport serialization/deserialization should be done in a separate method, for the same reasons.

These two methods would both take callbacks. Here is a re-write:

// Given a client, queries for user
function retrieveUser( client, username, password, cb) {
  client.query('select * from "user" where username = $1 and password = $2', [username, password], function(err, users){
    if(err) {
      cb(err);
    }
    else if(users.rowCount < 0) {
      cb(new Error("No user found for username ="+username));
    }
    else {
      cb(null, result.rows[0]);
  });
}

//Uses passport to serialize/deserializeUser
function passportSerialize(user, cb){
      async.series([
       function(callback) {
         passport.serializeUser(user, function(res, done) {
           callback(null, res);
         }
       },
       function(res, callback){
         if(res) {
           passport.deserializeUser(res, function(res, done) {
              if(res) {
                 callback(null, res);
              } else {
                 callback(new Error('deserializeUser failed'));
              } 
           });
         } else {
           callback(new Error('SerializeUser failed'));
         }
       }
    ], cb);
}
function check_auth_user(username, password) {
    var client = new pg.Client("pg://user:pass@127.0.0.1/database");
    async.waterfall([
      client.connect,
      function(callback) {
        retrieveUser(client, username, password, callback);
      },
      function(user, callback) {
            passportSerialize(user, callback);
      }
    ], function(err, result) {
       if(err)
          console.err(err);
        else
          console.log("User authenticated, let her in");
    });
}

I hope you can see how this is much much better.

Node.js/Async - How to avoid callback hell with async? - Stack Overflo...

node.js node-async
Rectangle 27 0

no no... I have already implemented this, basically I want to know why the callback hangs ? and how to avoid nested callbacks.

@Gowsikan, how would you know if getData(i) is completed and returned a value ? thing is some time callback do not give you output immediately based on the task assigned or priority to nodejs thread (if I am not wrong).

@Aman Return a promise and resolve the deferred when you reach the else branch in the inner loop.

this method is just to call next method only after get the response of previous(may be a success or fail). If u put a for loop the loop will end before u get the response.

javascript - NodeJS: invoking callback function inside a for loop - St...

javascript node.js callback
Rectangle 27 0

Take a look at the async npm module. It helps with organizing callbacks and avoiding the deep nesting you are referring to. Perhaps the waterfall would help.

javascript - Nested Callbacks with NodeJS & MySQL - Stack Overflow

javascript node.js callback
Rectangle 27 0

I'm not familiar with CoffeeScript, please correct me and I'll edit this answer.

all: (req,res)->
    var result = wait.forMethod(@em.collection(@collection).find(), "toArray")
    roadmaps = []
    for r in result
        r.user = @getUser(r.user.oid)
        roadmaps.push r
    res.send(roadmaps)



 getUser: (oid)->
    try
      return wait.forMethod(@em.collection('user'),"findOne",{_id:new @objectId(oid)})
    catch(err)
      return undefined

As you can see, for "getUser", if the method is that simple, you better use your version, with the callback.

node.js - Using wait.for with nodejs and mongoskin to avoid callback h...

node.js mongodb coffeescript mongoskin
Rectangle 27 0

There are ways to combat runaway nesting using functional programming techniques. I use the curry module to break loop bodies out into stand-alone routines; usually this carries a very minor performance hit versus nesting (study curry for why). Example:

var curry = require('curry'),
    async = require('async');

var eachBody = curry(function(context, item, callback) {
  callback(null, context + item);  // first argument is error indicator
});

function exampleLoop(data, callback) {
  // use the curried eachBody instead of writing the function inline
  async.map(data, eachBody(data.length), callback);
}

function print(err, result) {
  console.log(result);
}

exampleLoop([2, 4, 6], print);  // prints [5, 7, 9]
exampleLoop([2, 4, 6, 7], print);  // prints [6, 8, 10, 11]
var async = require('async');

function exampleLoop(data) {
  async.map(data, function(item, callback) {
    callback(null, data.length + item);  
  }, function(err, result) {
    console.log(result);
  });
}

exampleLoop([2, 4, 6]);  // prints [5, 7, 9]
exampleLoop([2, 4, 6, 7]);  // prints [6, 8, 10, 11]

The second example is more compact, but the more nesting you add, the less readable it becomes. Also, by splitting up the implementation, you can reuse component functions in multiple ways, and you can write unit tests for the individual component functions, not only for the high-level functionality.

Node.js/Async - How to avoid callback hell with async? - Stack Overflo...

node.js node-async