0

I created a CRUD with NodeJS / Mongoose, split the files in MVC style. In route example I show up below, when the retrieveOne routine is executed, it's necessary to wait for its processing and then redirect the user to one route or another. I'd like to use Bluebird to wait for processing. I need some help to implement the routine.

Index.js -----------------------------------------------

const myCRUD = require('./api/controllers/controller')

router.post('/login', function(req, res, next) {   

   // HOW TO IMPLEMENT BLUEBIRD HERE?

   // How to wait for the "retrieveOne" process and a then do a "if" test (below)?   
   let ret = myCRUD.retrieveOne({ name: "abc test" }); 


   if(!ret) {
      res.redirect('/success')
   } else {
      res.redirect('/error')
   }
})

controller.js ------------------------------------------

const mongoose = require('mongoose');
const Schema = require('./schema-user');
const Model = mongoose.model('users', Schema);

const CRUD = {
   retrieveOne: function(query) {
      Model.findOne(query, function(err, result) {
         if (err) return err;
         return result;
      });
   }
}

module.exports = CRUD;

Note: I've already found several examples with and without Bluebird right here in S.O., but I couldn't get it to work: Examples: 1, 2, 3, 4, 5

wBB
  • 821
  • 1
  • 18
  • 39
  • As an aside, the query you are passing to retrieveOne looks a little wonky. Is that a typo? It should be something more like: `myCRUD.retrieveOne({ name: "abc test"});` – djheru Mar 26 '19 at 03:17
  • Yes, you're right. It's a typo. I've already fix that. – wBB Mar 26 '19 at 12:11

2 Answers2

3

You don't really need to use Bluebird for this, as mongoose works just fine with native Promises

In your controller:

const mongoose = require('mongoose');
const Schema = require('./schema-user');
const Model = mongoose.model('users', Schema);

const CRUD = {
   retrieveOne: function(query) {
      // findOne() returns a Promise ()
      // https://mongoosejs.com/docs/promises.html
      return Model.findOne(query);
   }
}

module.exports = CRUD;

Now, you can make your route handler an async function and just await the Promise

const myCRUD = require('./api/controllers/controller')

router.post('/login', async function(req, res, next) { 
   let ret = await myCRUD.retrieveOne({ name: "abc test"}); 
   if(!ret) {
      res.redirect('/success')
   } else {
      res.redirect('/error')
   }
})
djheru
  • 3,525
  • 2
  • 20
  • 20
  • I'm newbie to NodeJS and I think I keep doing something wrong. I made a copy and paste of your code, so It was presented the following error: `let ret = await myCRUD.retrieveOne(msgJSON);` error: `SyntaxError: await is only valid in async function`. Can you help me one more time? thanks! – wBB Mar 26 '19 at 12:16
  • 1
    Yep, you have to add `async` right before the function keyword `router.post('/login', async function(req, res, next) {` – djheru Mar 26 '19 at 14:31
  • Really .... I suppose I'd never see this `async` in the `post` line if you didn't show me it. Now it works! Thank you. – wBB Mar 26 '19 at 17:45
2

Using async and await

const myCRUD = require('./api/controllers/controller')
const Promise = require('bluebird');

router.post('/login', async function(req, res, next) {   

   // HOW TO IMPLEMENT BLUEBIRD HERE?

   // How to wait for the "retrieveOne" process and a then do a "if" test (below)?   
   let ret = await myCRUD.retrieveOne('{ name: "abc test"'); 


   if(!ret) {
      res.redirect('/success')
   } else {
      res.redirect('/error')
   }
})

// controller.js ------------------------------------------

const mongoose = require('mongoose');
const Schema = require('./schema-user');
const Model = mongoose.model('users', Schema);

const CRUD = {
   retrieveOne: function(query) {
      return new Promise((resolve, reject) => {
        Model.findOne(query, function(err, result) {
           if (err) reject(err);
           resolve(result);
        });
      });
   }
}

module.exports = CRUD;
djheru
  • 3,525
  • 2
  • 20
  • 20
ajai Jothi
  • 2,284
  • 1
  • 8
  • 16
  • Although this method works really well with most functions that use callbacks, it's actually not necessary here, because Model.findOne returns a promise, so there's no need to use the callback at all. – djheru Mar 26 '19 at 05:21
  • As in the *djheru* response, it also shown the following error: `let ret = await myCRUD.retrieveOne('{ name: "abc test"');` error `SyntaxError: await is only valid in async function`. I made some modifications and get to make it work partially, but I couldn't get back `result` nor `err`. :( – wBB Mar 26 '19 at 12:29
  • If it is modified to this way, it works: `myCRUD.create(myQuery).then((result) => { console.log(result); }).catch((err) => { console.log(err); })`. Also, It must remove this `let ret = await` from line of function `myCRUD.retrieve`. – wBB Mar 26 '19 at 12:59