Node.js : Using Promises with mongoosejs

来源:互联网 发布:c和指针好还是c语言好 编辑:程序博客网 时间:2024/05/01 02:15

http://blog.revathskumar.com/2015/07/using-promises-with-mongoosejs.html

I was using mongoosejs for connecting mongoDB from my NodeJS app. When an action involve mulitple queries it tend to be callback hell.

I didn’t used populate method for loading related data to demonstate the promises.

I start with connecting mongoose with the mongoDB.

// connection.jsvar mongoose = require('mongoose');mongoose.connect('mongodb://localhost/my_db');var db = mongoose.connection;db.on('error', console.error.bind(console, 'Connection Error : '));db.once('open', function(){  console.log('Connection ok!');});module.exports = mongoose;

And mongoose models looks like

// User model// models/user.jsvar mongoose = require('../connection');var Schema = mongoose.Schema;var ObjectId = Schema.ObjectId;var UserSchema = new Schema({  email: String,  access_token: String,  name: String,  username: { type: String,required: true, index: { unique: true, sparse: true }}});//Project model// models/project.jsvar mongoose = require('../connection');var Schema = mongoose.Schema;var ObjectId = Schema.ObjectId;var ProjectSchema = new Schema({  name: String,  user_id: {type: ObjectId, ref: 'User'},});//Issue model// models/issue.jsvar mongoose = require('../connection');var Schema = mongoose.Schema;var ObjectId = Schema.ObjectId;var IssueSchema = new Schema({  title: String,  body: String,  project_id: {type: ObjectId, ref: 'Project'},});

So when I need to list all the issues of a project I need to fetch the User then the Project and the list issues of that project. Let the route for the action like /:username/:project/issues. So Initially my action code looks like,

var User = require('./models/user');var Project = require('./models/project');var Issue = require('./models/issue');exports.index = function (req, res) {  var username = req.params.username;  var project = req.params.project;  User.findOne({username: username}, function(err, user){    if(err) {      console.log(err);      return    }    Project.findOne({name: project, user: user._id}, function(err, project){      if(err) {        console.log(err);        return      }      Issues.find({project_id: project._id}, function(err, issues){        if(err) {          console.log(err);          return        }        res.render('./views/issues/index', {user: user, project: poject, issues: issues});      })    });  });}

But this code looks difficult to maintain for me. I usually uses promises to avoid callback hell. So I thought of using promises with mongoosejs since they have inbuilt support for it. So I rewrote my code with promises

var User = require('./models/user');var Project = require('./models/project');var Issue = require('./models/issue');exports.index = function (req, res) {  var username = req.params.username;  var project = req.params.project;  User.findOne({username: username}).exec()    .then(function(user){      var result = [];      return Project.findOne({name: project, user_id: user._id}).exec()        .then(function(project){          return [user, project];        });    })    .then(function(result){      var project = result[1];      return Issues.find({project_id: project._id}).exec()        .then(function(issues) {          result.push(issues);          return result;        })    })    .then(function(result){      var user = result[0];      var project = result[1];      var issues = result[2];      res.render('./views/issues/index', {user: user, project: project, issues: issues});    })    .then(undefined, function(err){      //Handle error    })}

Have you noticed the use of exec() method? In mongoose, exec method will execute the query and return a Promise. We can make this code even better using populate method, Since I am learning this is far better than before and let the populate method be subject for another blog post. ;)

Comments are welcome.


0 0
原创粉丝点击