I'm creating a childprocess when an express api is called after saving some info in mongodb. This is the api part
router.get("/create", function(req, res) {
let Schema = new New({
Id: crypto.randomBytes(16).toString("hex"),
Status: "Online"
});
Schema.save(function(err) {
if (err) {
console.log(err);
} else {
let child = exec(`node ${modulepath}`, (error, stdout) => {
if (error) {
throw error;
}
console.log(child.stdout);
});
New.update({
"botId": Schema.Id
}, {
"ProcessId": child.pid
}).then((err) => {
if (err) {
console.log(err);
} else {
console.log("pid updated");
}
});
Id = Schema.Id;
module.exports = {
Id
};
}
});
});
What i'm trying to do here is, at the bottom i'm exporting an id which ideally should be exported to the childprocess instance but that is not happening. In the childprocess, if i import the id by const Id = require("./routes").Id; and try to access some info through it by
await New.findOne({
"Id": Id
}, function(err, b) {
if (err) {
throw err;
} else {
//some task
}
});
I'm not able to access the info as mongodb cant get the id. I know i'm going wrong in passing the value to the childprocess part but what is the solution?
Related
My app crashes when an empty value is passed in query.
db.collection.update({_id:1234},{ $pull: { "": {code:321} } })
Error :
UnhandledPromiseRejectionWarning: MongoError: An empty update path is not valid.
How can I handle this situation without crashing the app.
Below is my code.
{
try {
const db = client.db(dbName);
db.collection(cName).updateOne({ _id: id }, { $pull: query }).then((err, result) => {
if (err) {
callBack(err);
} else {
callBack(null, result);
}
});
client.close();
}
catch (err) {
callBack({
error: 'Unable to process the request',
errorMessage: err
})
}
}
You can validate your query by simply adding if condition before passing it to the MongoDB as below:
{
try {
if(query["field"]){ // Name of field from which you wants to pull
const db = client.db(dbName);
db.collection(cName).updateOne({ _id: id }, { $pull: query }).then((err, result) => {
if (err) {
callBack(err);
} else {
callBack(null, result);
}
});
client.close();
}else{
/** QUERY NOT FOUND OR INCORRECT QUERY PASSED **/
}
}
catch (err) {
callBack({
error: 'Unable to process the request',
errorMessage: err
})
}
}
I have the following code which I'm using to learn how to transition from callbacks, through to async, then moving onto promises and finally await.
For the first time, I'm really struggling to understand why I get nothing at all returned to the console.
I have several logging events in place, but these never trigger inside the code, and non of the errors are thrown / exceptions raised.
I have put in additional logging outside the functions to demonstrate that the files running when requesting eg, nodemon app.js from the terminal. However, the terminal hangs on 'starting'.
What am I doing wrong?
In addition to the code here, I have tried extensively wrapping different parts in try / catch blocks, but nothing is ever returned.
index.js:
const mysql = require('mysql');
const async = require('async');
const dbConfig = require('./db');
const employees = require('./employees');
async.series(
[
function(callback) {
mysql.createConnection(dbConfig, function(err) {
callback(err);
});
},
function(callback) {
employees.getEmployee(101, function(err, emp) {
if (err) {
callback(err);
return;
}
console.log(emp);
});
}
],
function(err) {
if (err) {
console.log(err);
}
}
);
employees.js:
const mysql = require('mysql');
const async = require('async');
function getEmployee(empId, getEmployeeCallback) {
async.waterfall(
[
function(callback) {
mysql.createConnection(function(err, conn) {
if (err) {
console.log('Error getting connection', err);
} else {
console.log('Connected to database');
}
callback(err, conn);
});
},
function(conn, callback) {
conn.execute(
`select *
from employees`,
function(err, result) {
if (err) {
console.log('Error executing query', err);
} else {
console.log('Query executed');
}
callback(err, conn, result);
}
);
}
],
function(err, conn, result) {
if (err) {
getEmployeeCallback(err);
} else {
getEmployeeCallback(null, result.rows[0]);
}
// If error getting conn, no need to close.
if (conn) {
conn.close(function(err) {
if (err) {
console.log('Error closing connection', err);
} else {
console.log('Connection closed');
}
});
}
}
);
}
module.exports.getEmployee = getEmployee;
db.js:
var mysql = require('mysql');
var connection = mysql.createConnection({
host:'localhost',
user:'developer',
password:'superseceretpassword',
database:'testing'
});
connection.connect(function(err) {
if (err) throw err;
});
module.exports = connection;
I am writing this code as a project for a customer
and when i go to a show route i got this 500 internal server error
http.get('/files/:id', function(req, res) {
var vid;
var pap;
Videos.find({}, function(err, videos) {
if (err) {
console.log(err);
} else {
vid = videos;
}
});
Papers.find({}, function(err, file) {
if (err) {
console.log(err);
} else {
pap = file;
}
});
Material.findById(req.params.id, function(err, found) {
if (err) {
console.log(err);
} else {
res.render('files', {
file: pap,
video: vid,
current: found
});
}
});
});
this is my show route code.
Note : if i reload the page the error is gone and the page open.
The reason is you need to wait for all the database queries to finish before rendering. In your code, it is possible for the page to render before the other two queries have completed and returned their data. The good news is that Mongoose supports Promises for asynchronous functions.
http.get('/files/:id', function(req, res) {
Promise.all([
Videos.find({}).exec(),
Papers.find({}).exec(),
Material.findById(req.params.id).exec()
]).then( ([video, paper, material]) => {
res.render('files', {
file: paper,
video: video,
current: material
});
}).catch( error => console.log(error) );
});
The functions you're using with Mongoose are asynchronous in nature; the variables vid and pap are not initialized when you run res.render. When you attempt to use those variables in your frontend (template like Jade, Handlebars EJS, I don't know what you're using), they are undefined, and subsequently cause the 500 error. You'll need to run the functions such that the results of all Mongoose queries are available to res.render when it runs; either using an async NodeJS library, or calling each function within one another and then calling res.render at the end.
Solution 1: Using async Node module
var async = require('async');
async.parallel([
// Each function in this array will execute in parallel
// The callback function is executed once all functions in the array complete
function (cb) {
Videos.find({}, function(err, videos) {
if (err) {
return cb(err);
} else {
return cb(null, videos);
}
});
},
function (cb) {
Papers.find({}, function(err, papers) {
if (err) {
return cb(err);
} else {
return cb(null, papers);
}
});
},
function (cb) {
Material.findById(req.params.id, function(err, found) {
if (err) {
return cb(err);
} else {
return cb(null, found);
}
});
}
], function (err, results) {
if (err) {
// If any function returns an error
// (first argument), it will be here
console.log(err);
}
else {
// Even though the functions complete asynchronously,
// the order in which they are declared in the array
// will correspond to the position in the array
// if it returns anything as a second argument.
var videos = results[0];
var files = results[1];
var found = results[2];
res.render('files', {
file: files,
video: videos,
current: found
});
}
});
Solution 2: Nested Callbacks
Videos.find({}, function(err, videos) {
var vid = videos;
if (err) {
console.log(err);
} else {
Papers.find({}, function(err, file) {
var pap = file;
if (err) {
console.log(err);
} else {
Material.findById(req.params.id, function(err, found) {
if (err) {
console.log(err);
} else {
res.render('files', {
file: pap,
video: vid,
current: found
});
}
});
}
});
}
});
So i have implemented a mongodb on my nodejs server. And what I have done is store users via:
function insertUser() {
var collection = dbb.collection('user');
var user1 = {name: user, token: token};
collection.insert(user1, function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
}
function findUserByName(devName) {
var collection = dbb.collection('user');
collection.find({name: devName}).toArray(function (err, result) {
if (err) {
console.log(err);
} else if (result.length) {
console.log('Found: ', result);
selectedUserToken = result.token;
} else {
console.log('No document found');
insertUser();
}
dbb.close();
});
}
So result will equal:
Found: [ { _id: 57be1cadc281c03ea116c9ab,
name: 'Austin Hunter',
token: 'dJyXVjMJk08kXWrua8SUjKb....SxACihKZoR53y_wOZmcFNKMmD5q99QNvsp3flL' } ]
My question is, how can I get that token out to equal selectedUserToken so I can send a push notification with gcm? Right now result.token is undefined.
You should use findOne() instead of find() since you only expect a single result back:
function findUserByName(devName) {
var collection = dbb.collection('user');
collection.findOne({name: devName}, function (err, result) {
if (err) {
console.log(err);
} else if (result) {
console.log('Found: ', result);
selectedUserToken = result.token;
} else {
console.log('No document found');
insertUser();
}
dbb.close();
});
}
But if you wanted to leave your code as is with the find() you would just retrieve the first element of the resulting array retrieved by find()
function findUserByName(devName) {
var collection = dbb.collection('user');
collection.find({name: devName}).toArray(function (err, result) {
if (err) {
console.log(err);
} else if (result.length) {
console.log('Found: ', result);
selectedUserToken = result[0].token;
} else {
console.log('No document found');
insertUser();
}
dbb.close();
});
}
Maybe result[0].token, because result is an array of user items.
Currently I have the following callback system:
var saveTask = function(err, result) {
if (err) return callback(err, result);
var newid = mongoose.Types.ObjectId();
var task = new Task({
_id: newid,
taskname: req.body.name,
teamid: req.body.team,
content: req.body.content,
creator: req.user.userId
});
task.save(function (err) {
if (!err) {
log.info("New task created with id: %s", task._id);
return callback(null, task);
} else {
if(err.name === 'ValidationError') {
return callback('400', 'Validation error');
} else {
return callback('500', 'Server error');
}
log.error('Internal error(%d): %s', res.statusCode, err.message);
}
});
};
if (req.body.team) {
valTeam.isMember(req.body.team, req.user._id, function (err, done) {
if (err) {
saveTask('403', 'Not the owner or member of this team');
} else {
saveTask(null, true);
}
});
} else {
saveTask(null, true);
}
valTeam.isMember
exports.isMember = function(teamid, userid, callback) {
Team.find({'_id':teamid, $or:[{'creator': userid }, {'userlist': { $in : [userid]}}]}, function(err, result) {
if (err) return err;
console.log(result);
if (!result.length)
return callback('404', false);
else
return callback(null, true);
});
}
In short, if team is sent by POST, I'm checking if the user is member of that ID in valTeam.isMember. Am I using the correct syntax and best method to call back my saveTask function to save the task if the user is part of the team?
This code currently works, but I feel like there should be an easier way to do it? How could I use a promise to achieve the same thing?
Thanks in advance.
It's curious the fact that you create objects instead Schemas. However "every head is a different world", this is my way:
task.save(function(error, data){
if (error) {
trow error;
} else {
//Make whatever you want here with data
});