Issues working on SailsJS WebSocket - node.js

I'm getting response in
io.socket.on('chats', function (e, v) {
console.log(e)
});
when using the code block bellow.
io.socket.get('/chats', function (e, s) {
console.log(e);
});
So, main setup are okay. Then I tried to customize a bit. I wanted to pass room id to get messages from specific room instead of fetching unnecessary messages. But no response on new item addition when using
io.socket.get('/chats/get?room=PJ1RcnwbBxsH3xZn', function (e, s) {
console.log(e);
});
However that was able to fetch initial data properly as used return res.json(chats); in ChatsController.get
From ChatControllers.js
module.exports = {
get: function (req, res) {
if(!req.session.authenticated){
return res.json({error: true, message: 'You must be logged in to join chat.'})
}
if (!req.isSocket) {
return res.json({error: true, message: 'Inappropriate request format'})
}
sails.log(req.param('room'));
if(!req.param('room')){
return res.json({error: true, message: 'Inappropriate room ID'})
}
Chats.find({room: req.param('room')}).populate('user').exec(function (err, chats) {
if (err) {
return res.serverError(err);
}
Chats.subscribe(req, _.pluck(chats, 'id'));
return res.json(chats);
});
},
.....
I've added Chats.subscribe(req, _.pluck(chats, 'id')); to subscribe.
Cannot understand what I've missed in get action. I searched but didn't get good tutorial. So exploring documentation, I tried those. Can you advice to fix the issue?
Thanks

I found solution after more research. sails.sockets.join() and sails.sockets.broadcast() was my toy.
Thanks however.

Related

What return value of sequelize when update?

I am write API in expressjs with Sequence. But I got problem with return value when update!
I follow a tutorial on internet but it got error when num=[1] not num=1 although updating success!
exports.update = (req, res) => {
const { id } = req.params;
Post.update(req.body, {
where: { id }
})
.then((num) => {
if (num === 1) {
res.send({
message: 'Post was updated successfully.'
});
}
else {
res.send({
message: `Cannot update Post with id=${id}. Maybe Post was not found or req.body is empty!`
});
}
})
.catch((err) => {
res.status(500).send({
message: `Error updating Post with id=${id}`
});
});
};
So, what return value after call update method? and how do I solve it? Thanks.
The sequelize document of update is
public static async update(values: object, options: object): Promise<Array<number, number>>
Promise<Array<number, number>>
The promise returns an array with one or two elements. The first element is always the number of affected rows, while the second element is the actual affected rows (only supported in postgres with options.returning true).
So, it will not return only the number. you need to follow the document.
To resolve
.then((nums) => {
const num = nums[0]
.....

Return 404 code in proper way instead empty array

I have an quite simple application the idea is that someone has unique code which value are stored in one mongo collection in other we are keeping some data which we need to return if the key was found in first collection.
As probably you have noticed I'm using NodeJS with MongoDB and Mongoose, Express.
I have a problem with method bellow:
exports.getCompanyByKey = function(req, res) {
console.log(req.params.keyvalue);
var query = Company.where({keyValue : req.params.keyvalue});
query.findOne(function(err, company){
if(err){
res.send(err);
}else{
SampleData.findOne({}, function(err, sample_data){
if(err)
res.send(err);
res.json(sample_data);
});
}
});
};
The problem is that it will always return the data beause it's not throwing an error but empty array - so is there any other good and proper way as it should be don to throw 404 error without statement such as if(length<0) res.status(404).send('Error message).
I simply want to minimalize amount of if statements.
Maybe there is some other way to write implementation od error handling for mongoose which in general instead returning empty array will give us error code with message?
It's not exactly clear what you're asking, but if you want to make an error condition out of something that is not normally an error, then an if statement (or some other test like that) is required to test for that specific condition.
You could make your own function for querying that turns an empty response into an error and you could "hide" the if condition in that function if you want, but it's still an if condition that tests for your specific condition.
So, to return a 404 if the array is empty, you would just add an if statement (as you already appear to know):
exports.getCompanyByKey = function(req, res) {
console.log(req.params.keyvalue);
var query = Company.where({keyValue : req.params.keyvalue});
query.findOne(function(err, company){
if(err){
res.status(500).send(err);
} else {
SampleData.findOne({}, function(err, sample_data){
if(err) {
res.status(500).send(err);
} else {
if (sample_data.length) {
res.json(sample_data);
} else {
res.status(404).send("no data");
}
}
});
}
});
};
FYI, you also need to make sure you are properly setting a status code when there's an error and that you are never sending multiple responses to the same request (even when there's an error). I've also fixed several cases of those issues in your code.
This could likely be written cleaner and responses consolidated by using the promise interface to your database and send an error in one .catch().
For example, you could simplify your code by creating a utility function for .findOne() that detects and sends an error response automatically:
function findOne(res, db, q, cb) {
db.findOne(q, function(err, data) {
if (err) {
res.status(500).send(err);
cb(err);
} else if (!q.length) {
res.status(404).send("no data");
cb(new Error("no data"));
} else {
cb(null, data);
}
});
}
Then, your function could be simplified to this:
exports.getCompanyByKey = function(req, res) {
var query = Company.where({keyValue : req.params.keyvalue});
query.findOne(function(err, company){
if(err){
res.status(500).send(err);
} else {
findOne(res, SampleData, {}, function(err, sample_data) {
// any error response has already been sent
if (!err) {
res.json(sample_data);
}
});
}
});
};
Again, this would be better to use your Db's promise interface.

What does meen this error: Falsy value for recipient key 'registrationTokens'

I got this error: Falsy value for recipient key 'registrationTokens' while working with gcm push notifications.
Below you can find my code:
Device.find({ user: { $in: users }}, function (err, devices) {
if (err) {
logger.error('500 ' + err)
return res.status(500).json({
code: config.errorCode.status500.code,
message: config.errorCode.status500.message
})
}
var androidRegTokens = []
var iOSReqTokens = []
for (var i = 0; i < devices.length; i++) {
if (devices[i].platform == 'Android') {
androidRegTokens.push(devices[i].deviceToken)
} else {
iOSReqTokens.push(devices[i].deviceToken)
}
}
if (androidRegTokens.length > 0) {
gcmPush('Notification is sent.', androidRegTokens)
}
if (iOSReqTokens.length > 0) {
apnsPush('Notification is sent.', iOSReqTokens)
}
return res.json({ msg: 'Operation succeed.'})
})
Body of the function gcmPush('Notification is sent.', androidRegTokens) is:
this.sender.send(message, { registrationTokens: deviceTokens }, function (err, response) {
if (err) {
console.error(err)
}else {
console.log(response)
}
})
Does anyone know what wrong is with my code? At first push notifications worked perfect, than this error occured each time I call the service.
EDIT:
I have solved this thanx to Luiz Fernando. The problem is the function:
gcmPush('Notification is sent.', androidRegTokens)
I have forgot to add title which is part of the constructor:
function GcmPush (title, message, deviceTokens) {
this.sender = new gcm.Sender(config.gcmSender)
this.sendPushNotification(title, message, deviceTokens)
}
The deviceTokens object is a falsy value, it can be: null, undefined, 0, '', NaN,false.
Maybe it happend because you are filling iOSReqTokens and androidRegTokens nested in an asynchronous operation (it seems Device.find is async). So, the callback of Device.find and the for-loop happens in different times. Probably, the for-loop is happening AFTER the response, so this response will be undefined (and really is).
So, you need to use some async control flow library, such Promise or Async and ensure the correct order of operations.
Also, where you use the pushed registrations?

Mongoose save() doesn't actually save

I am trying to find my record, update it, and save it. I can see the data updated and it can still show the updated data inside the callback of save(). However, when I go to the database, it is actually not updated:
Skills.findOne({ skillsCat: req.body.skillsCat }, (err, gets)=> {
if (err) {
res.send(err)
return
}
if (gets && gets.skillName.indexOf(req.body.skillName) !== -1) {
// Here I update my data
gets.percent[gets.skillName.indexOf(req.body.skillName)] = req.body.percent
Console.log(gets); // Here I can see the data is updated
return gets.save((err, updated)=> {
Console.log(updated); // Here I can see the data is updated
if (err) { return }
res.json({
message: 'Skill updated successfully',
data: updated
})
})
} else {
return
}
})
Is there anyone encounter similar issues before and help me out with this? Thanks.
Try below code :
gets.percent[gets.skillName.indexOf(req.body.skillName)] = req.body.percent
Console.log(gets); // Here I can see the data is updated
//Notice that 'fieldname' is the name of actual field in database
gets.markModified('fieldname');
return gets.save((err, updated)=> {
Console.log(updated); // Here I can see the data is updated
if (err) { return }
res.json({
message: 'Skill updated successfully',
data: updated
})
})

Query parsing in mongodb

I am passing a query parameter which is look like this
var str="["56557e9e8091afc81a4371c8","565ac01b076fd1141492b594","565ab985076fd1141492b586","565aba0a076fd1141492b58c","565ab9d3076fd1141492b588","565aba4b076fd1141492b58e"]";
and it is being received into my node api which is look like this
console.log(req.query.pageModalIds);
now I want parse my query like this
return RuleSetModel.find({ 'pageId': { $in: req.query.pageModalIds } }, function (err, ruleset) {
if (!err) {
console.log('get rule set');
return res.send(ruleset);
} else {
res.statusCode = 500;
console.log('Internal error(%d): %s', res.statusCode, err.message);
return res.send({ error: 'Server error' });
}
});
This method does not provide my data. what is my fault. Thanks.
N.B This is working If i set as fixed parameter which is below..
return RuleSetModel.find({ 'pageId': { $in: ["565a9fddf84313fc08b260dc","565ac01b076fd1141492b594"] } }, function (err, ruleset) {
I think the problem lies with req.query.pageModalIds. Since you are not doing any processing to that it likely stays as a String Object. You need to convert it into array object before applying to query.A sample is shown below,
var pageModalIds = JSON.parse(req.query.pageModalIds)
After this you can apply $in query on this new variable. Try this and let me know. :)

Resources