Princi Ya
Princi Ya

Reputation: 131

How to avoid callback hell in nodejs for sequelize

I am using Sequelize and ending up in callback hell:

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

I want to avoid callback hell and make the code more reusable. Is there a way to do this without using async, promises etc?

Suppose I write something like this..

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

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

The problem with this approach is that, get_user renders the page first and then the callback from get_users is executed, giving me users as always null.

Please help me in this regard!

Thanks in advance!

Upvotes: 3

Views: 4078

Answers (2)

Jan Aagaard Meier
Jan Aagaard Meier

Reputation: 28788

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

Upvotes: 4

radar155
radar155

Reputation: 2220

Try this:

  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);
        });
    }

Upvotes: 0

Related Questions