0

Background: I have a PHP background and this is my first application using MEAN stack.

I need to save a record but before I must to check if there is any record under the same id already saved in the DB. In PHP I would do something like this: Once the user clicks "Save": 1) Call the function to check if an entry with that id already exists 2) If it doesnt, call the save function.

In Javascript, I'm getting a little confused with Promises and so on.

Can somebody give me some light here?

Right now, I'm doing the following: In the save api, I call this function to check if the record already exists in the DB: recordExists = findTranscationByBill(billId);

function findTransactionByBill(billId){
     results = new promise(function(resolve, reject){
        Transactions.find({billId : billId},function(err, transactions){
            if(err)
                reject("Error: "+err);

            //console.log(transactions);
            resolve(transactions);
         });  
     });

     results.then(function(data){
        console.log('Promise fullfilled: '+ data);
     }, function(error){
        console.log('Promise rejected: ' + error);
     }); 

  return $results;
}

The problem is that I think I'm not using promise properly, as my variable doesn't get populated (because its Async). In the console.log I see that the promise is being fulfilled however, the variable returns as [object Object] I'm stucked with this problem because I don't know if I should carry on thinking as PHP mindset or if there is a different approach used in Javascript.

Thanks in advance!

Deisy Laymi
  • 343
  • 1
  • 2
  • 10

3 Answers3

0

I think the right function is:

function findTransactionByBill(billId){
  var results = new promise(function(resolve, reject){
     Transactions.find({billId : billId},function(err, transactions){
        if(err) {
           reject(err);
        } else { 
           if (transactions.length === 0) {
              reject('No any transaction');
           } else {
             //console.log(transactions);
             resolve(transactions);
           }
     });  
 });

 results.then(function(data){
    console.log('Promise fullfilled: '+ data);
 }, function(error){
    console.log('Promise rejected: ' + error);
 }); 

 return results;
}

And then use it like this:

recordExists = findTranscationByBill(billId);
recordExists.then(function() {
    // resolved, there are some transactions
}, function() {
    // rejected. Error or no any transactions found
    // may be you need to check reject result to act differently then no transactions and then error
});
Olegas
  • 10,349
  • 8
  • 51
  • 72
0

In my opinion you could just as well use a callback for this, and since MongoDB has a count method, why not use it

function findTransactionByBill(billId, callback){

    Transactions.count({billId : billId}, function(err, count){
        if (err) {
            callback(err, false);
        } else {
            callback(null, count !== 0);
        }
    });

}

and to use it

findTransactionByBill(billId, function(err, exists) {
   if (err) {
      // handle errors
   } else if ( ! exists ) {
      // insert into DB
   }
}
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • You're welcome. Remember that promises **are** great, they get you out of callback hell, but at the same time, just plain old callback is how most things are done in Node, and they work just fine for simple convenience methods like this one. – adeneo Dec 27 '14 at 14:01
  • I disagree, promises are never great if you are using them like the OP was because you are still doing callbacks (with all the drawbacks) but with added ceremony. Deferred anti-pattern is real. – Esailija Dec 28 '14 at 12:18
0

I assume you are using mongodb native drive.

I think mongodb doesn't have promise built-in supported. So you have to promisify it by a little help from promise library. Please refer this if you want to use bluebird.

After promisifying, the code should looks like that (using bluebird):

Promise = require('bluebird');
// Promisify...
var _db = null;
var client = MongoClient.connectAsync('mongodb://localhost:27017/test')
    .then(function(db) {
        _db = db
        return db.collection("myCollection").findOneAsync({ id: 'billId' })
    })
    .then(function(item) {
      if (item)
        _db.save(item);
    })
    .catch (err) {
      // error handling 
    }

The above code is not perfect, because it introduced a global var, so the better version may be

Promise = require('bluebird');
// Promisify...
var client = MongoClient.connectAsync('mongodb://localhost:27017/test')
    .then(function(db) {
        return Promise.prop({ 
          item: db.collection("myCollection").findOneAsync({ id: 'billId' }, 
          db: db
        })
    })
    .then(function(result) {
      var item = result.item;
      var db = result.db
      if (item)
        db.save(item);
    })
    .catch (err) {
      // error handling 
    }

You need to check bluebird to know how to use it. Also they are many other promise libraries like q, when, but all are similar stuff.

Community
  • 1
  • 1
Ron
  • 6,037
  • 4
  • 33
  • 52