Ong Kong Tat
Ong Kong Tat

Reputation: 1242

How should I implement asynchronous function in Javascript with node.js and Mongodb?

So far I have seen that there are setTimeout(),process.nextTick(function) for asynchronous function however I have no clue as to how to use it. I have tried on my code since I need a asynchronous function right now but it will have Can't set headers after they are sent.

This is my code:

var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/myproject';

var updateRecord = function(db, req, callback) {
db.collection('documents').updateMany({ 'Item Description': 
req.body.itemDescrip }, {
    $set: { 'Issued QTY': req.body.issueQty }
}, function(err, results) {
    if (err) return callback(err);
    console.log('Done');
    console.log(results);
    var cursor = db.collection('documents').find({
        'Item Description': req.body.itemDescrip,
        'Issued QTY': req.body.issueQty
    });
    var temp = [];
    cursor.each(function(err, doc) {
        if (err) {
            return callback(err);
        } else{
        console.log('Successfully queried');
        console.log(doc);
        temp.push(JSON.stringify(doc));
        }
    });
    callback(null, temp);
});
};

 module.exports = {
    postCollection: function(req, res) {
    var issueQty = req.body.issueQty;
    var itemDescrip = req.body.itemDescrip;
    MongoClient.connect(url, function(err, db) {
        if(err) {
          res.send(err);
          res.end();
          db.close();
          return;
        }
        updateRecord(db, req, function(err, doc) {
            if(err){
              res.send(err);
            }
            else{
              //setTimeout(function(){
                  res.send(doc);
            //},2000);
            }
            res.end();
            db.close();
        });

    });
 }
}

Basically I am trying to implement an asynchronous function such that it will execute the updateRecord first before sending a response down below as right now without the setTimeout, all I get it [] due to executing both simultaneously. This is for my web api which I am testing via postman. Any help is appreciated, thanks!

Update: Finally it worked! However my output has \included in it which is rather weird since I did not put \in the db. This is according to Roman Maksimov code below.

[
  "{\"_id\":\"18A\",\"Inventory for NTA SAM Cards\":\"\",\"Item Description\":\"Auresys EZL Prod\",\"Corrupted QTY\":\"\",\"Closing QTY\":\"100\",\"Remarks\":\"\",\"Opening QTY\":\"1000\",\"Issued QTY\":\"100\"}",
  "{\"_id\":\"20\",\"Inventory for NTA SAM Cards\":\"\",\"Item Description\":\"Auresys EZL Prod\",\"Corrupted QTY\":\"\",\"Closing QTY\":\"100\",\"Remarks\":\"\",\"Opening QTY\":\"1000\",\"Issued QTY\":\"100\"}",
  "null"
]

Upvotes: 1

Views: 72

Answers (2)

gngchrs
gngchrs

Reputation: 478

cursor.each is asynchronous, so, having the callback inside it may achieve unexpected results.

An easier way to achieve what you want is to remove the each function from the cursor and use the toArray method of mongodb. Add the final callback inside the toArray callback

var cursor = db.collection('documents').find({
  'Item Description': req.body.itemDescrip,
  'Issued QTY': req.body.issueQty
}).toArray(function(err, docs) {
  if (err) {
    return callback(err);
  }
  return callback(null, docs)
});

Upvotes: 1

Roman Maksimov
Roman Maksimov

Reputation: 1635

Seems your are do it under the Node.js (Am I right?). From your desciription it's not clear what are you really want to reach. But, obviously, you can't send a body to a response since you have ended it (from this point the response is already sent to the client and, of course, it's not possible to write to it). Try this:

updateRecord(db, req, function(err, doc) {
    if(err){
        res.send(err);
        res.end();
    } else {
        setTimeout(function(){
            res.send(doc);
            res.end();
        }, 2000);
    }
    db.close();
});

Upvotes: 1

Related Questions