Weird Bug in my Javascript Scope - javascript

I Have run across a weird bug, where an exported function completely ignores the passed parameter and instead generates its own parameter.
My code is as follows:
exports.returnThumbs = function(req, res) {
var params = '{}, {thumb: 1}';
console.log(params);
PictureService.find(params, function(err, response){
if(err){
res.send(err);
} else {
console.log(response);
res.send(response, 'binary');
}
});
}
Which calls:
// Finds Answer by Passed Parameters
exports.find = function(params, callback){
console.log(params);
PictureModel.find(params, function(err, response){
if(err){
console.log(err);
callback({'error': 'Error retrieving answers'});
} else{
if(!response){
callback({'error': 'There are no pictures from this user_id'});
} else{
callback(null, response);
}
}
});
}
this should clearly pass '{}, {thumb: 1}' as the parameter, but the console.log instead prints: { user_id: 'thumbnails' } which is very weird. No matter what I do, renaming, refactoring. it always prints this as a parameter.

I ended up tracing it back to my router. I was parsing the request inappropriately.

Related

Trouble with callbacks, error catching and MongoDB

I've been working on an application which allows me to add companies to a database. Originally my code was pure spaghetti, so I wanted to modularize it properly. For this purpose, I added routes, a controller and a dao.
This is how my code looks right now
Routes
app.post('/loadcompanies', (req, res)=> {
companiesController.loadcompany(req.body, (results)=>{
console.log(results);
res.send(200, "working!");
})
})
Controller
module.exports.loadCompany = (body, callback)=>{
companiesDao.loadCompany(body, callback);
}
Dao
module.exports.loadCompany = (company, callback)=>{
MongoClient.connect(conexionString, (err, database) => {
if (err) console.log(err);
db = database;
console.log(company);
db.collection('companies').insert(company, (err, result)=>{
callback({message:"Succesfully loaded company", company:result});
});
})
}
My current concern is that working with errors when modularizing like this is confusing. I tried adding a try-catch method around the db insert and throwing and error if there is one, but that doesn't seem to work. Other things I've tried is returning the error in the callback, like this:
if (err) callback (err, null);
but I end up getting a "Can't set headers after they are sent." error.
How would you handle errors in this situation? For example, in the case that someone tries to add a duplicate entry in an unique element.
You should be able to simply do the error checking inside the callback for the insert function:
db.collection('companies').insert(company, (err, result)=>{
if (err) {
callback(err, null);
return;
}
callback(null, {message:"Succesfully loaded company", company:result});
});
If you get an error like you say, that's probably because the database is actually returning an error. You could also make your errors more specific, like:
module.exports.loadCompany = (company, callback)=>{
MongoClient.connect(conexionString, (err, database) => {
if (err) {
callback(new Error('Connection error: ' + err.Error());
return;
}
db = database;
console.log(company);
db.collection('companies').insert(company, (err, result)=>{
if (err) {
callback(new Error('Insertion error: ' + err.Error());
return;
}
callback(null, {message:"Succesfully loaded company", company:result});
});
})
Here is your loadCompany done in async / await format.
Notise there is no need for error checking, errors will propagate as expected up the promise chain.
Note I've also changed loadCompany to be an async function too, so to call it you can simply do var ret = await loadCompany(conpanyInfo)
module.exports.loadCompany = async (company)=>{
let db = await MongoClient.connect(conexionString);
console.log(company);
let result = await db.collection('companies').insert(company);
return {message:"Succesfully loaded company", company:result};
}

async watefall doesn't call the functions

So i am actually woking on a simple program with node.Js and i have an issue using async.waterfall :
I created a function in my user model that connect the user by accessing the database, here is the code :
exports.connection = function (login,password) {
async.waterfall([
function getLogin(callback){
usersModel.findOne({ login: login }, function (err, res) {
if (err){
callback(err,null);
return;
}
if(res != null ){
// test a matching password if the user is found we compare both passwords
var userReceived = res.items[0].login;
callback(null,userReceived);
}
});
},
function getPassword(userReceived, callback){
console.log(userReceived);
callback(null,'done')
}
], function(err){
if (err) {
console.error(err);
}
console.log('success');
});
}
Using node-inspector i figured out that the main issue(I think) is that when it enters the waterfall function it doesn't execute the callback function of findOne it literally skips this and directly jump to the getPassword function (which isn't executed too).
so if someone could help me figuring out what's the problem that would be nice since i'm on it for around two days now.
Thank you
EDIT:
After adding the different missing cases of tests(which was why the callback didn't worked) I have this connection function:
exports.connection = function (login,password) {
async.waterfall([
function getLogin(callback){
usersModel.findOne({ login: login }, function (err, res) {
console.log('login: ',res.login);
console.log('erreur: ',err);
if (err){
callback(err,null);
return;
}
if(!res)
{
console.log('getLogin - returned empty res');
callback('empty res');
}
if(res != null ){
// test a matching password if the user is found we compare both passwords
var userReceived = res;
callback(null,userReceived);
}
});
},
function getPassword(userReceived, callback){
console.log('login received :',userReceived.login);
var Ulogin = userReceived.login;
var Upassword = userReceived.password;
// function that compare the received password with the encrypted
//one
bcrypt.compare(password, Upassword, function(err, isMatch) {
if (err) {
console.log(err);
callback(err,null);
return;
}
else if (isMatch) {
console.log('Match', isMatch);
callback(null,isMatch);
}
else {
console.log('the password dont match', isMatch);
callback('pwd error',null);
}
});
},
], function(err){
if (err) {
console.error('unexpected error while connecting', err);
return false;
}
console.log('connected successfully');
return true;
});
}
And in my main file server.js i'm doing currently doing :
var connect = users.connection(login,password);
//the goal is to use the connect variable to know if the connection
//failed or not but it's 'undefined'
if(connect){
res.send('youyou connecté');
}
else {
res.send('youyou problem');
}
this absolutely don't work so i tried to use Q library but I have an error saying
"TypeError: Cannot read property 'apply' of undefined at Promise.apply"
here is the code using Q:
app.post('/signup', function (req, res) {
var login = req.body.login;
var password = req.body.password;
Q.fcall(users.connection(login,password))
.then(function (connect) {
if(connect){
res.send('connected');
}
else {
res.send('problem');
}
})
.catch(function (error) {
throw error;
})
.done();
});
but i am a little bit astonished i thought that by using async.waterfall() i told the function to wait until it received all the callbacks return so i don't understand why the connect variable is 'undefined'?
What I don't understand is - what was the flow exactly? did 'usersModel.findOne' get called?
What I see that is missing here in the getLogin function is a callback in the case that both the 'if' statement return false. in this case you'll get stuck in the first function and you won't advance to 'getPassword' function.
If this still doesn't work, please try executing the following code and report what was printed:
exports.connection = function (login,password) {
async.waterfall([
function getLogin(callback){
usersModel.findOne({ login: login }, function (err, res) {
if (err){
console.log('getLogin - error has occured');
callback(err,null);
return;
}
if(!res)
{
console.log('getLogin - returned empty res');
callback('empty res');
}
console.log('getLogin - result seems OK');
// test a matching password if the user is found we compare both passwords
var userReceived = res.items[0].login;
callback(null,userReceived);
}
});
},
function getPassword(userReceived, callback){
console.log('getPassword');
console.log(userReceived);
callback(null,'done')
}
], function(err){
if (err) {
console.error(err);
}
console.log('success');
});
}

Trying to create a function nodejs express

Im trying to create a function so i dont use the same code again and again but i keep getting internal error.I get the data and then i get the internal error so if i change something i need to refresh the page to be updated.I cant understand why i get the error.Here is the error
GET http://localhost:3000/api/pages 500 (Internal Server Error)
Object {data: "", status: 500, config: Object, statusText: "Internal Server Error"}
code:
function Get(some,that,res){
return some.find(function(err,that) {
if (!err) {
return res.send(that);
} else {
return res.send(500, err);
}
});
};
router.get('/pages', sessionCheck, function() {
Get(Page,pages,res);
});
UPDATE: i might doing something wrong so lets take it from the start.How can i create a function that do that so i dont reuse the same code again and again.
router.get('/pages', function(request, response) {
return Page.find(function(err, pages) {
if (!err) {
return response.send(pages);
} else {
return response.send(500, err);
}
});
});
and here is my full code
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Page= require('../models/page.js');
var bcrypt = require('bcrypt-nodejs');
function Get(some,that,response){
return some.find(function(that,err) {
if (!err) {
return response.send(that);
} else {
return response.send(500, err);
}
});
};
router.get('/pages', sessionCheck, function(request,response) {
Get(Page,pages,response);
});
router.METHOD will first call your function sessionCheck. You will then need to call next() within sessionCheck to call the next function, in which you are not defining any parameters (typically you would define req, res).
If you are using express your function call should probably be:
function someGetFunc(req, res, next)
You have res as the third parameter, so that might be the problem.
Now the Get function you have above is internal to an anonymous function that doesn't take in params, so what you are passing into it are either undefined or reference global scope variables.
ok i fixed it like that i shouldnt have left the function empty it required res,req
function Get(Some,that,res){
return Some.find(function(err,that) {
if (!err) {
return res.send(that);
} else {
return res.send(500, err);
}
});
};
router.get('/pages', sessionCheck,function(req,res) {
Get(Page,pages,res);
});

Pulling information from API and adding it to database (MEAN stack)

I feel like a complete moron but me and a friend are working on a project together and having trouble getting the first route to return the items requested from the Etsy API and have getAllListings add the items to the database. If you can see something glaringly obvious that we are doing wrong please let me know.
I should also mention that while the statement console.dir(body) does print out the items to the terminal it does not look like the contents are being passed to GET '/api/etsy/getListings'
Thanks!
routes.js
//this i want to return a list of active listings from the users shop.
app.get('/api/etsy/getListings',function(req, res){
bEtsy.getAllListings(req, res, function(err, body) {
});
res.json(req.body);
});
bEtsy.js
var standardCallback = function (err, status, body, headers, callback) {
if (err) {
console.log(err);
return callback(err, null);
}
if (body) {
console.dir(body);
return callback(null, body); // this gives me an error
}
}
var getAllListings = function(itemId, callback){
var Item = mongoose.model('Item');
var listingsParams = {
include_private: true
}
etsy.auth().get(
'/shops/'+etsy.shop+'/listings/active',
listingsParams,
function(err, status, body, headers){
var newi = new Item({name: body.title, stock: body.count, owner: "00000000000000000000",
etsy:{listingId: body.listing_id, stock: body.count}});
newi.save(function(err){
if (err) return handError(err);
});
standardCallback(err, status, body, headers, callback);
}
);
};
You are calling this function with three parameters, when it only takes two
bEtsy.getAllListings(req, res, function(err, body) {
});
On top of that the first argument itemId is being passed the request object and then it is also never used inside the function itself but some global variable called listingsParams is?!?

How get values out of a callback? (NodeJs + Mongoose)

I'm not too good with callbacks, and now I have problems to find a document with mongoose but use the document in the same action/controller before send a response.
uploadFile = function(req,res) {
var _objs = {};
function retrieveUser(objs,username, callback) {
User.findOne({ 'username': username })
.exec(function(err, user){
if(err) callback(err,null,null);
else callback(null,user,objs);
});
}//retrieveUser()
retrieveUser(_objs,req.body.user,function(err,user,_objs) {
if(err) console.log('ERROR: ' + err);
_objs.user = user;
console.log(_objs.user);
});
console.log(_objs);
}
So, inside the callback function the console.log() shows the object rightly, but the second console.log() shows me _objs as empty. Well, I need to fill _objs with other objects as attributes, How can I acchieve that?
Everything is working as designed. Your code will be executed as follows:
retrieveUser(_objs,req.body.user,function(err,user,_objs) {
// will be executed when the retrieveUser function completes is tasks...
if(err) console.log('ERROR: ' + err);
_objs.user = user;
console.log(_objs.user);
});
// ...meanwhile, execution will continue here.
console.log(_objs); // depending on how fast retrieveUser calls the callback, _objs will be set or (more likely) not set.
You can either continue the control flow of your application inside the callback or use frameworks like Streamline.js, async.js, Step, Seq, IcedCoffeeScript, promise.js, ...
Well this is what I did. At really for what I expected that is something similar to what I do in controllers in others frameworks of others languages, query for some entities and create another one that will be related to the previous that was queried.
uploadPic = function(req, res, next) {
var username = req.body.user,
estId = req.body.est;
async.series([
function(callback) {
User.findOne({ 'username': username})
.exec(function(err, user){
if(err) return callback(err);
if(!user) return callback(new Error("No user whit username " + username + " found."));
callback(null,user);
});
},
function(callback) {
Est.findById(estId)
.exec(function(err,est) {
if(err) return callback(err);
if(!est) return callback(new Error("No Est with ID " + estId + " found"));
callback(null,est);
})
},
],function(err,results){
if(err) return next(err);
console.log(results);
/// do my own stuffs here!
});// end async.series()
}

Categories

Resources