Hello guys here is my code:
function get_group(req, res, next) {
var send_result = function(err, group_list) {
[...]
res.send(group_list);
return next();
};
Group.findOne({'_id': req.params._id}, send_result);
}
Now how can I implement the async library (caolan) using async.series and combine the findOne() with send_result, the code as it is look pretty disorganised to me.
EDIT1:
I used this strategy but I am not sure is correct, any suggestion?
function get_group(req, res, next) {
async.waterfall([
function(callback) {
Group.findOne({'_id': req.params._id}, callback);
}
],
function (err, group_list){
res.send(group_list);
return next();
});
}
Any suggestion?
For what they call routes in Express.js you actually almost never need to use the async library. The reason is that routes are actually a sort of control flow them self. They take as many middleware as you want so you can divide your routes into small blocks of code.
For example lets say you want to get one record/document from a database do something with it and then send it as json. Then you can do the following:
var getOne = function(req, res, next){
db.one( 'some id', function(err, data){
if (err){
return next( { type: 'database', error: err } );
};
res.local( 'product', data );
next();
});
};
var transformProduct = function(req, res, next){
var product = res.locals().product;
transform( product, function(data){
res.local('product', data);
next();
});
};
var sendProduct = function(req, res, next){
var product = res.locals().product;
res.json(product);
};
app.get( '/product', getOne, transformProduct, sendProduct );
If you write middleware for your routes like this you'll end up with small building blocks you can easily reuse throughout your application.
Related
route.js
router.get('/restful', function(req, res){
console.log("before");
User.show_deatils(req, res, function(err, resultArray){
if(!err) {
req.session.resultArray=resultArray;
}
});
console.log(req.session.resultArray);
res.render('restful',{resultArray:req.session.resultArray});
});
I don't know why I am getting as undefined when I am doing it console.log() in the above position.If I do console.log() just after the req.session.resultArray=resultArray then we are getting the result array.
I want to display this resultArray in my view.ejs. Can anyone suggest me how to solve it.What is the thing I am missing it out?
The console.log runs before the async function actually gets the details from the database. so you get undefined.
Do the render inside the callback. i.e, after you assign result array to session.
router.get('/restful', (req, res, next) {
User.show_deatils(req, res, function(err, resultArray) {
if(!err) {
req.session.resultArray=resultArray;
return res.render('restful' {resultArray:req.session.resultArray}));
}
});
});
Just do like this
router.get('/restful', function(req, res){
console.log("before");
User.show_deatils(req, res, function(err, resultArray){
if(!err) {
res.render('restful',{resultArray:resultArray});
}
});
});
I think this is what you want.
I'm new to Node, and Javascript in general. I'm working with the request module to get a JSON response from a web service. I'm not sure if it'd be best to turn my request into a function, or embed the request inside of another function. I haven't had any luck either way.
// Module imports
var express = require('express');
var router = express.Router();
var request = require('request');
var options = {
url: 'https:www.example.com/wow.json',
auth: {
user: 'user',
password: 'pass',
json: true
}
}
request(options, function (err, res, body) {
if (err) {
console.log(err);
return;
}
requestResult = JSON.parse(body); // All data
wowUsage = requestResult.publishers[0].used;
});
// Sending data to the template view
router.get('/', function(req, res, next) {
res.render('template', {tempVar: wowUsage});
});
module.exports = router;
Whenever I start up my web server, this code executes once, and then it's done. Refreshing the page won't load any new information. Should I embed the request in a function, and then call that function in my router.get statement? I tried to nest the request in a function, but I couldn't make that work at all.
If you put the request in a separate function, make sure to add a callback parameter to the new function that gets called with the appropriate data. For example:
function getJSON(callback) {
request(options, function(err, res, body) {
if (err)
return callback(err);
try {
callback(null, JSON.parse(body).publishers[0].used);
} catch (ex) {
callback(ex);
}
});
}
router.get('/', function(req, res, next) {
getJSON(function(err, wowUsage) {
if (err) {
console.log(err.stack);
return res.status(500);
}
res.render('template', {tempVar: wowUsage});
});
});
Currently I am working on a nodeJS API, I have a model, and that model can have Media items, as you can see in my code here:
router.get('/:id', function(req, res, next) {
qbuilder.byId(Model,req)
.exec(
function(err,model){
Media.count({'model.entity': model._id}, function(err, media){
if(media){
console.log(media);
}
});
model.total_media = 15;
responders.sendJsonOrError(err, res, model, next);
});
});
Problem is, that the code:
model.total_media = 15;
Is not showing up in the responder, which is strange, because if I clean the object with: model = []; it returns empty.
Once I add lean() to my query, it returns the total_media in the responder, but then I get the problem that when I do like this:
router.get('/:id', function(req, res, next) {
qbuilder.byId(Model,req)
.exec(
function(err,model){
Media.count({'model.entity': model._id}, function(err, media){
if(media){
model.total_media = media;
}
});
responders.sendJsonOrError(err, res, model, next);
});
});
It is not populating the total_media, is there any other way to do this correctly?
Try with this. The response is sending before you assign values.
router.get('/:id', function(req, res, next) {
qbuilder.byId(Model,req)
.lean().exec(
function(err,model){
Media.count({'model.entity': model._id}, function(err, media){
if(media){
model.total_media = media;
}
responders.sendJsonOrError(err, res, model, next);
});
});
});
I'm learning express and am currently writing an API, and have this structure:
app.route('/api/brief/:_id')
.get(function(req, res, next) {
// Check if the _id is a valid ObjectId
if (mongoose.Types.ObjectId.isValid(req.params._id)) {
// Do something
}else{
// Error
}
})
.put(function(req, res, next) {
// Check if the _id is a valid ObjectId
if (mongoose.Types.ObjectId.isValid(req.params._id)) {
// Do something
}else{
// Error
}
})
.delete(function(req, res, next) {
// Check if the _id is a valid ObjectId
if (mongoose.Types.ObjectId.isValid(req.params._id)) {
// Do something
}else{
// Error
}
});
Ideally I'd like to avoid the repetition (checking the validity of the ID).
Is there a way that I can structure the route as to avoid that repetition?
There are a few ways you can approach it. There is the app.all() method:
app.all("/api/*", function(req, res, next) {
if (req.params._id) {
if (mongoose.Types.ObjectId.isValid(req.params._id)) {
return next();
}
else {
// error handle
}
}
next();
});
Personally, I don't like catch-alls. I'd rather be more explicit:
function validateMongooseId (req, res, next) {
if ( mongoose.Types.ObjectId.isValid(req.params._id) ) {
return next();
}
else {
// error handle
}
}
function handleGet(req, res, next) {}
function handlePost(req, res, next) {}
function handlePut(req, res, next) {}
app.post("/api/brief", handlePost);
app.get("/api/brief/:_id", validateMongooseId, handleGet);
app.put("/api/brief/:_id", validateMongooseId, handlePut);
I put the .post() in there to demonstrate why I don't like the catch-all. It clearly doesn't apply to that endpoint. You may have other middleware functions that apply to it, so I'd rather explicitly have them on the endpoints that use them.
With the following controller, how can I call one method from another in the same controller?
Specifically, calling login() within a successful signup(), while retaining the same functionality for login() when it is used by a form?
The line this.login(newUser) does not work, nor does plain old login(newUser)
In both scenarios, I get the error:
TypeError: Cannot call method 'login' of undefined
var mongoskin = require('mongoskin');
module.exports = {
login: (function (req, res) {
req.db.collection('auth').findOne({_id: mongoskin.helper.toObjectID(req.body.id)},
function (err, results) {
// log person in and send results to client
}
)
}),
signup: (function (req, res) {
var user = req.body;
req.db.collection('auth').insert(user, function (err, newUser) {
// after adding user, automatically log them in
// does not work:
//login(newUser, function (err) {
// do something
//})
// does not work:
this.login(newUser, function (err) {
// do something
})
}
)
})
}
Controllers should be doing as little as possible, and should orchestrate the work required by executing functions stored elsewhere.
View this gist - click here
What I have done is created "services" that are not tied to the client request, therefore re-usable everywhere.
Hope this helps.
Thanks to Dave Newton
var mongoskin = require('mongoskin');
var myCollection = 'auth';
Solution
function localLogin(db, myCollection, user, res){
db.collection(myCollection).findOne({_id: mongoskin.helper.toObjectID(user._id)},
function(err, user){
res.send({ token: createToken(user) });
});
module.exports = {
login: (function (req, res) {
var user = req.body;
localLogin(req.db, myCollection, user, res)
},
signup: (function (req, res) {
var user = req.body;
req.db.collection(myCollection).insert(user, function (err, newUser) {
// after adding user, automatically log them in
localLogin(req.db, myCollection, newUser, res)
})
}
) }) }