MongooseJS Save won't call callback - node.js

I am using MongooseJS to connect to MongoDB
I am creating a a new Team. Once I save the team, I want to add a reference to the team for my user. But unfortunately, whenever I go to add the team to my user and save the user my callback is not called. Any ideas why?
TeamRepository.prototype.createForUser = function(user, data, callback) {
var team,
_this = this;
if (user == null) {
user = null;
}
if (data == null) {
data = {};
}
if (callback == null) {
callback = (function() {});
}
team = new Team({
name: data.name,
description: data.description,
state: data.state
});
return this.save(team, function(err) {
if (err) {
return callback(err, team);
} else {
user.teams.push({
team: team._id
});
return _this.save(user, function(err) {
return callback(err, team);
});
}
});
};
Specifically this line. Notice I have two nested saves.
return _this.save(user, function(err) {
return callback(err, team);
});
Any help would be great.

I have solved the issue. In my user model, I had hooked into the save event and was not calling next() to move along the save.
schema.pre('save', function(next) {
var _this = this;
if (this.isNew || this.isModified('password')) {
return hashPassword(this.password, function(err, hash) {
if (err) {
return next(err);
}
_this.password = hash;
return next();
});
} else {
return next(); // missing this
}
});
And here is what my TeamRepository.save() looks like since you asked.
TeamRepository.prototype.save = function(model, callback) {
if (model == null) {
model = null;
}
if (callback == null) {
callback = (function() {});
}
if (model) {
model.increment();
return model.save(callback);
} else {
if (callback) {
return callback(null);
}
}
};

Related

Update from bd with success but returns undefined on Controller Node.Js

Hy everyone, I'm having some troubles with my rest api. I have in my ui a button where I click to update the state of a bus ( visible / not visible). By clicking on the button I can update the state of the item on the map.
So my problem is when I update the info in my DB in my controller i get the result of this as undefined but the resolve of the db returns
{"command":"UPDATE","rowCount":1,"oid":null,"rows":[],"fields":[],"_parsers":[],"RowCtor":null,"rowAsArray":false}
My return.rows[0] becomes undefined on resolve (I console.log this value and i dont understand why this is happening).
ServicesController.js
ServicesController.prototype.updateMap = function (req, res, next) {
var data = req.body;
if (isEmptyObject(data)) {
res.status(400).send({error: errorMessage.emptyBody});
return;
}
if (data.sn === undefined || data.sn === "") {
res.status(400).send({error: "Invalid serial number"});
return;
}
Database.Services.getDeviceBySn(data.sn).then(function (device) {
var map_data={
"isRoot": data.root,
"visible": data.visible
}
Database.Services.addMapInfo(map_data, device.id).then(function (map) {
console.log("updateMap depois do addMapInfo --- map >>> ", map);
if (map) {
res.status(200).send(map);
} else {
res.status(404).end();
}
}).catch(function (e) {
res.status(500).send(e);
});
}).catch(function (e) {
res.status(500).send(e);
});
}
ServicesDatabase.js
ServicesDatabase.prototype.addMapInfo = function (data, deviceId) {
return new Promise(function (resolve, reject) {
pg.connect(dbStatsConnectionString, function (err, client, done) {
if (err) {
reject(err);
return
}
client.query("UPDATE device_services SET data=jsonb_set(data::jsonb,'{map}',$1::jsonb,true), modified_date=NOW() WHERE device_id=$2", [data, deviceId], function (err, result) {
done();
if (err) {
reject(err);
} else {
resolve(result.rows[0]);
}
});
});
});
}
My parameters are data {"isRoot":"false","visible":"online"} and deviceId "1f110136-9490-4ea5-a46d-3fdfa65ea0ab"
My controller always return 404 because of this
if (map) {
res.status(200).send(map);
} else {
res.status(404).end();
}
Anyone can help me? I dont get it...

I need help about Asynchronus call in node.js with Mongodb, i need to call synchronous method for further processing of data

calling id from mongodb with callback function
var GetID = function (nameval, callback) {
console.log(nameval);
console.log("munesh hello");
GenerateID.find({ "id_name": nameval }, {
"id_code": 1,
"id_value": 1, "_id": 0
}, function (err, genvalue) {
if (err) {
console.log('hello');
}
else {
if (genvalue === null) {
callback(err, false);
}
else {
callback(err, true);
}
}
console.log(genvalue);
});
};
and calling above method so we need
so we need id from GenerateID.GetID and do our own work.
var region_id = GenerateID.GetID(name, function (error, result) {
if (error) {
console.log("getting any error");
} else {
console.log(region_id);
if (!result) {
console.log('data is not coming');
} else {
console.log('data is coming');
}
}
});
You have a number of issues. In the first piece of code, you need to pass the actual value when calling the callback.
In the second, you need to set region_id = result.
Ideally you would do this using promises as demonstrated below.
var GetID = function(nameval){
return new Promise((resolve,reject) => {
console.log(nameval);
console.log("munesh hello");
GenerateId.find({ "id_name" : nameval },{"id_code":1 , "id_value":1, "_id":0},
function( err , genvalue ) {
console.log(genvalue);
if (err) {
console.log('hello');
return reject()
}
if (genvalue == null) { return resolve(false); }
return resolve(genValue);
});
});
}
var GetIDPromise = GenerateId.GetID(name);
GetIDPromise.then(
genValue => {
if ( genValue == false ){
console.log('data is not coming');
// handle region id not being available. Perhaps return and show an error
}else{
var region_id = genValue;
// continue execution and use region id.
}
},
error => {
console.log("getting any error");
}
)

Session is not defined sailsjs

I'm writing a policy checkSession which basically destroy session after some time.
checkSession.js (policies/checksession.js)
var moment = require('moment');
function checkLastActivity(req) {
if (!req.session.lastActivity) {
return false; // no session.
} else {
return true;
}
}
function setActivity(req) {
req.session.lastActivity = moment(new Date()).format();
return true;
}
function updateActivity(req, res, updated) {
req.session.lastActivity = moment(new Date()).format();
updated(null, {
isdestroted: 0
});
}
function checkIdleTime(req, idleTime) {
try {
var lastActivityTime = moment(req.session.lastActivity).format();
var currentActivityTime = moment(new Date()).format();
timeIdle = moment.utc(moment(currentActivityTime).diff(moment(lastActivityTime))).format("HH:mm:ss");
minutestimeIdle = moment.duration(timeIdle).asMinutes().toFixed(2);
idleTime(null, minutestimeIdle);
} catch (e) {
idleTime(e, null);
}
}
function destroyActivity(req, res, destroyed) {
try {
req.session.destroy();
sails.log.info("***********************session is expired for user *****************");
destroyed(null, {
isdestroted: 1,
redirectCode: 200,
redirectView: '/login/'
});
} catch(e) {
destroyed(e, null);
}
}
module.exports = function isSession(req, res, next) {
cleanParamsService.cleanPrm(req);
async.waterfall([
function(callback) {
callback(null, checkLastActivity(req));
},
function(isLastActivity, callback) {
if (isLastActivity) {
checkIdleTime(req, function(err, timeIdle) {
if (minutestimeIdle > sails.config.session_timeout) { /*if user is being idle*/
destroyActivity(req, res, function(err, destroyed) {
sails.log.warn('User was idle since' + minutestimeIdle + ', sessions are destroyed');
callback(null, destroyed);
})
} else {
updateActivity(req, res, function(err, updated) {
callback(null, updated);
});
}
})
} else {
updateActivity(req, res, function(err, updated) {
callback(null, updated);
});
}
}
], function(err, result) {
if (result) {
if (result.isdestroted == 0) {
return next();
} else {
return res.redirect(result.redirectCode, result.redirectView);
}
} else {
sails.log.error('err:', err);
return res.badRequest();
}
});
};
now if i change it to
var moment = require('moment');
function checkLastActivity(req) {
if (!req.session.lastActivity) {
return false; // no session.
} else {
return true;
}
}
function setActivity(req) {
req.session.lastActivity = moment(new Date()).format();
return true;
}
function updateActivity(req, res, updated) {
req.session.lastActivity = moment(new Date()).format();
updated(null, {
isdestroted: 0
});
}
function checkIdleTime(req, idleTime) {
try {
var lastActivityTime = moment(req.session.lastActivity).format();
var currentActivityTime = moment(new Date()).format();
timeIdle = moment.utc(moment(currentActivityTime).diff(moment(lastActivityTime))).format("HH:mm:ss");
minutestimeIdle = moment.duration(timeIdle).asMinutes().toFixed(2);
idleTime(null, minutestimeIdle);
} catch (e) {
idleTime(e, null);
}
}
function destroyActivity(req, res, destroyed) {
try {
req.session.destroy();
sails.log.info("***********************session is expired for user *****************");
destroyed(null, {
isdestroted: 1,
redirectCode: 200,
redirectView: '/login/'
});
} catch (e) {
destroyed(e, null);
}
}
module.exports = function isSession(req, res, next) {
cleanParamsService.cleanPrm(req);
async.waterfall([
function(callback) {
callback(null, checkLastActivity(req));
},
function(isLastActivity, callback) {
if (isLastActivity) {
checkIdleTime(req, function(err, timeIdle) {
if (minutestimeIdle > sails.config.session_timeout) { /*if user is being idle*/
destroyActivity(req, res, function(err, destroyed) {
sails.log.warn('User was idle since' + minutestimeIdle + ', sessions are destroyed');
callback(null, destroyed);
})
} else {
updateActivity(req, res, function(err, updated) {
callback(null, updated);
});
}
})
} else {
updateActivity(req, res, function(err, updated) {
callback(null, updated);
});
}
},
function(resp, callback) {
if (resp.isdestroted == 0) {
req.fresh;
req.session.isdestroted = false;
callback(null, resp);
} else {
req.fresh;
req.session.isdestroted = true;
callback(null, resp);
}
}
], function(err, result) {
if (result) {
if (result.isdestroted == 0) {
return next();
} else {
return res.redirect(result.redirectCode, result.redirectView);
}
} else {
sails.log.error('err:', err);
return res.badRequest();
}
});
};
The application trigger error where i'm setting req.session.isdestroted = true/false and the error is
warn: User was idle since0.38, sessions are destroyed
debug: Lowering sails...
C:\Users\Vbase002\Desktop\CC\Website\api\policies\checkSession.js:83
req.session.isdestroted = true;
^
TypeError: Cannot set property 'isdestroted' of undefined
at C:\Users\Vbase002\Desktop\CC\Website\api\policies\checkSession.js:83:41
at fn (C:\Users\Vbase002\Desktop\CC\Website\node_modules\sails\node_modules\
async\lib\async.js:579:34)
at Immediate._onImmediate (C:\Users\Vbase002\Desktop\CC\Website\node_modules
\sails\node_modules\async\lib\async.js:495:34)
at processImmediate [as _immediateCallback] (timers.js:367:17)
i'm setting this session to show some message on login page to user, but i don't know why sails is behaving like this.
is there any way to handle this scenario and also please let me know the reason why this is happening.
Thanks
This is a behavior from express.
Session.destroy()
Destroys the session, removing req.session, will be re-generated next
request.
As your warn log indicates, req.session.destroy(); has been called before the error.
You could use req.session.regenerate() to have the expected behavior.
Session.regenerate()
To regenerate the session simply invoke the method, once complete a
new SID and Session instance will be initialized at req.session.

Converting async code to q/promise code in nodejs

I've read through a lot of different articles on promisejs but can't seem to get it to work for my code. I have async code that works and does what I need but it's very long and doesn't look as clean as it could with promise.
Here's the two links I've been really looking into: http://jabberwocky.eu/2013/02/15/promises-in-javascript-with-q/ and https://spring.io/understanding/javascript-promises.
mainCode.js
accountModel.findOne({username: body.username}, function(err, usernameFound) {
console.log("here");
if (err) {
console.log(err);
} else {
console.log("here1");
anotherClass.duplicateUsername(usernameFound, function(err, noerr) {
if (err) {
console.log("error");
res.status(409).send("username");
} else {
console.log("here2");
accountModel.findOne({email: body.email}, function(err, emailFound) {
if (err) {
console.log("error2");
} else {
console.log("here3");
console.log(emailFound);
}
});
}
});
}
});
// anotherclass.duplicateUsername
anotherClass.prototype.duplicateUsername = function(usernameFound, callback) {
if (usernameFound) {
callback(usernameFound);
} else {
callback();
}
}
current promise code (in mainCode.js):
var promise = userModel.findOne({
username: body.username
}).exec();
promise.then(function(usernameFound) {
console.log("usernameFound")
return userCheck.duplicateUsername(usernameFound);
}).then(function(usernameFound) {
console.log("NOERR:" + usernameFound + ":NOERR");
console.log("noerror");
return;
}, function(error) {
console.log(err);
console.log("error");
res.sendStatus(409);
return;
});
When I run my promise code, it goes to duplicateUsername, does callback() but then doesn't print anything in the promise code.
duplicationUsername needs to return a promise, otherwise the promise chaining will get the value returned from calling callback (which would be undefined).
Something like this should work:
anotherClass.prototype.duplicateUsername = function(usernameFound) {
var deferred = Q.defer();
if (usernameFound) {
deferred.resolve(usernameFound);
} else {
deferred.reject();
}
return deferred.promise;
}
So it seems like I needed to "promisify" my own functions before I could use them.
Here's how I did it with Q:
var Q = require('q');
anotherClass.prototype.duplicateUsername = function(username, callback) {
return new Promise(function(resolve, reject) {
var deferred = Q.defer();
if (usernameFound) {
deferred.reject("error);
} else {
deferred.resolve("no err: duplicate username");
}
deferred.promise.nodeify(callback);
return deferred.promise;
});
}
Here's how to do it with Bluebird:
userCheck.prototype.duplicateUsername = function(usernameFound) {
return new Promise(function(resolve, reject) {
if (usernameFound) {
reject("error");
} else {
resolve();
}
});
}
Then in my mainClass, I just used them by calling the methods and then .then(//blah)

nodejs usage of globals

I am new to NodeJS, but a pretty experienced programmer. I am working on a side project to get my feet wet with node. I am looking at MongoDB for storage. To get started I just wanted to test creating some basic CRUD functions in node. I have included my code below.
My question is regarding the global var 'updated'. It is used in the 'read' and 'update' functions to control which function gets called next. I would like to call them in the following order: create, read, update, read, delete.
It is my understanding that I cannot pass in a function parameter to 'read' to dictate which function to call next because this is called asynchronously and the lambda function I am defining as my callback to mongojs.read will not have the parent functions parameters to use.
What is the correct way to do this? Using a global feels like a hack. :)
// app.js
//<user>:<password>#<server>/<database>
var connection = "foo:bar#127.0.0.1/blah";
var collections = ["scores"]
var db = require("mongojs").connect(connection, collections);
//console.log(db);
var updated = false;
function my_create()
{
console.log("my_create");
db.leaderboard.save({name: "sunder", score: 42}, function(err, result) {
if(err || !result )
{
console.log("Score save failed");
console.log(err);
}
else
{
console.log("Score save successful");
my_read();
}
});
}
function my_read()
{
console.log("my_read");
// app.js
db.leaderboard.find({name: "sunder"}, function(err, results) {
if(err || !results)
{
console.log("Score read failed");
console.log(err);
}
else
{
results.forEach(function(score)
{
console.log(score);
});
// I am sure using globals is a HACK. Need to figure this out.
if(updated)
my_delete();
else
my_update();
}
});
}
function my_update()
{
console.log("my_update");
db.leaderboard.update({name: "sunder"}, {$set: {score: 1337}}, function(err, result) {
if(err || !result)
{
console.log("Score update failed");
}
else
{
console.log("Score update successful");
updated = true;
my_read();
}
});
}
function my_delete()
{
console.log("my_delete");
db.leaderboard.remove({name: "sunder"}, function(err, result) {
if(err || !result)
{
console.log("Score delete failed");
}
else
{
console.log("Score delete successful");
process.exit();
}
});
}
// kick off the flow of processes
my_create();
How about passing the next action to perform into the my_read() function like this:
// app.js
var connection = "foo:bar#127.0.0.1/blah";
var collections = ["scores"]
var db = require("mongojs").connect(connection, collections);
function my_create()
{
console.log("my_create");
db.leaderboard.save({name: "sunder", score: 42}, function(err, result) {
if(err || !result )
{
console.log("Score save failed");
console.log(err);
}
else
{
console.log("Score save successful");
my_read("update");
}
});
}
function my_read(next_action)
{
console.log("my_read");
// app.js
db.leaderboard.find({name: "sunder"}, function(err, results) {
if(err || !results)
{
console.log("Score read failed");
console.log(err);
}
else
{
results.forEach(function(score)
{
console.log(score);
});
// I am sure using globals is a HACK. Need to figure this out.
if(next_action === "delete")
my_delete();
else
my_update();
}
});
}
function my_update()
{
console.log("my_update");
db.leaderboard.update({name: "sunder"}, {$set: {score: 1337}}, function(err, result) {
if(err || !result)
{
console.log("Score update failed");
}
else
{
console.log("Score update successful");
updated = true;
my_read("delete");
}
});
}
function my_delete()
{
console.log("my_delete");
db.leaderboard.remove({name: "sunder"}, function(err, result) {
if(err || !result)
{
console.log("Score delete failed");
}
else
{
console.log("Score delete successful");
process.exit();
}
});
}
// kick off the flow of processes
my_create();

Resources