Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does mongoose findOne on model return a promise?

I have a simple Node module that exports a function that makes a database query. The problem is that this function returns before the database query completes.

"use strict";

var mongoose = require('mongoose'),
    Model    = require('./entities/user/model'),
    _        = require('underscore');

let dao = new Model(mongoose);

module.exports.isAdmin = function(user_id) {
  var params = {'roles': 'admin'};

  dao.findOne(params, function(err, user) {
    if (err) {
      logger.error(err);
      return false;
    }
    if (_.indexOf(user.roles, 'admin') != -1) {
      logger.info("admin user: " + user._id);
      if (user._id == user_id) return true;
    }
    return false;
  });
};

isAdmin function searches the users collection in order to find out if user_id belongs to admin user.

The problem is that isAdmin function doesn't wait for the response of findOne query.

How could I force the isAdmin function to return only when query returns results ?

like image 492
Matko Avatar asked Feb 26 '16 21:02

Matko


People also ask

What does Mongoose findOne return?

Returns: One document that satisfies the criteria specified as the first argument to this method. If you specify a projection parameter, findOne() returns a document that only contains the projection fields.

How does a Mongoose findOne work?

Mongoose | findOne() Function The findOne() function is used to find one document according to the condition. If multiple documents match the condition, then it returns the first document satisfying the condition.

Is Mongoose query a promise?

Mongoose queries are not promises. They have a .then() function for co and async/await as a convenience. However, unlike promises, calling a query's .then() can execute the query multiple times.

What does Mongoose exec return?

exec() function returns a promise, that you can use it with then() or async/await to execute a query on a model "asynchronous".


1 Answers

Because findOne is async function, one way to return from it is through callback function

module.exports.isAdmin = function(user_id, callback) {
  var params = {'roles': 'admin'};

  dao.findOne(params, function(err, user) {
    if (err) {
      logger.error(err);
      callback && callback(false);
    }
    if (_.indexOf(user.roles, 'admin') != -1) {
      logger.info("admin user: " + user._id);
      if (user._id == user_id)
          callback && callback(true);
    }
    callback && callback(true);
  });
};

isAdmin(userId, function(v) {
    console.log(v);
})

Another way is to get Promise in findOne, as this doc said, .exec() gives you a fully-fledged promise. Even with Promise, to meet you requirement, the result could be returned through callback function.

module.exports.isAdmin = function(user_id, callback) {
  var params = {'roles': 'admin'};

  var queryPromise = dao.findOne(params).exec();
  queryPromise.then(function(user) {
      if (_.indexOf(user.roles, 'admin') != -1) {
        logger.info("admin user: " + user._id);
        if (user._id == user_id)
          callback && callback(true);
      }
    }, function(err) {
      callback && callback(false);
  });
};
like image 122
zangw Avatar answered Oct 03 '22 18:10

zangw