简体   繁体   中英

Asynchronous issue within nodejs/mongodb code

I am new to nodejs/express/mongodb/jade and I have been trying for some time now to put together a simple site to help facilitate a more efficient way of reaching back to past data and being able to reuse it quickly. I determined the easiest way to us it would be do have a dynamic URL and had started to make good progress and then ran into a road block.

End Goal: I am looking to use the URL params to determine which data is returned. Ran locally the syntax would look like localhost/:collection/:id. As an example it'd look like: localhost/lastyear/aug2001. Thus the resulting page would display the data in the collection lastyear where the _ID is equal to aug2001.

To achieve this I currently I have the route in index.js set as:

var express = require('express');
var router = express.Router();

router.get('/:collection/:id', function(req, res) {
    var db = req.db;
    var collection = db.get(req.params.collection);
    var entry = collection.findOne({ id: req.params.id },{})
    res.render('dataentry',{ title: 'Information for: ' + req.params.collection + ' ' + req.params.id +'.', data: entry
    });   
});

module.exports = router;

The structure of a doc within the collection looks as something as follows:

{
     "_id": "aug2001"
     "header": "header text"
     "content": "content text"
     "item" : "items text"
}

For testing to see some form of data my jade file for dataentry looks as follows(I know tabbing is important in jade and it may not look correct here in the post but I made sure the tabs are correct):

block content 
     p Finding info...
     p= data.header
     p= data.content
     p= data.item

When navigating to /lastyear/aug2001 all I see is the page load "Finding info..." and I am not sure what I am missing as far as the jade syntax goes in order to display the doc data. I appreciate any help/suggestions of a more efficient way to achieve my end result.

EDIT: The real issue was not with JADE displaying but rather a asynchronous db call when pulling data out of the db.

From what i see you have asynchronous problem here.

Try like this

router.get('/:collection/:id', function(req, res) {
   var db = req.db;
   var collection = db.get(req.params.collection);
   //this is async operation so you need to wait until it finish.
   //and only then send response to page.
   collection.findOne({ id: req.params.id },{}, function(err, entry){
      res.render('dataentry',{ title: 'Information for: ' + req.params.collection + ' ' + req.params.id +'.', data: entry
      });  
   }); 
});

Hope this helps.

Code not checked


As @Mykola Borysyuk mentioned, this seems to be an asynchronous callback problem. In your code, collection.findOne({ id: req.params.id },{}) is an asynchronous function, so you have no idea when it will be executed. As you are rendering the page from outside the function callback, it would seem that entry is not modified before the rendering call occurs.

As mentioned in the above answer, one way to do this is by creating a callback function, and rendering the page from inside the callback. That would be as @Mykola showed. For sake of clarity, I'm giving it below.

var collection = db.collection(req.params.collection);
   collection.findOne({ id: req.params.id },{}, function(error, data){
     if(error){
       console.log("Error: " + error);
     }
     else {
       res.render('dataentry',{ title: 'Information for: ' + req.params.collection + ' ' + req.params.id +'.', data: data});
     }
   });

This should work fine. That being said, there is another way to make the rendering operation wait till the asynchronous function finishes execution. That can be done using promises.

That can be done like:

var collection = db.collection(req.params.collection);
res.promise(collection.findOne({ id: req.params.id },{},function(error,data)).then(function(){
    res.render('dataentry',{ title: 'Information for: ' + req.params.collection + ' ' + req.params.id +'.', data: data});
});

I haven't checked my code, but hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM