callback is not a function in node js - javascript

I am trying a simple operation that will result the particular users details from the database. Pooling database and all other connections work perfectly but the callback is not working. Am I doing anything wrong here?
Below is the code I use.
db_crud.js
var express = require('express');
var app = express();
var crud = require('./routes/crud_op_new.js');
var search = require('./routes/search.js');
var connection;
var result;
app.get('/search',(req,res)=>{
crud.connection(function (con) {
search.getuser(con,req.param('name'),result);
res.send(result);
});
});
app.listen(8003);
Finally here is where the error occurs ... search.js
exports.getuser = function(connection,req,callback){
console.log("GET Request iniciated");
connection.query("select * from user,addr where name=? and user.id=addr.e_id",[req],(err,row)=>{
if(err){
callback("DB ERROR: "+err);
}
else {
if(row.length==0){
callback("No Records found");
}
else {
callback(row);
}
}
});
}
The db_crud will send the credentials to search.js and here the callback is called to send result. crud_op_new.js creates the db pool connection and is in variable con.

As mentioned by Jaromanda X in the answer, result is just declared and unassigned which should be a callback function.
Also, the callback in search.js is being returned the error and result both as the first argument. You have to change this callback(row) to callback(null, row) to handle the error and result as below.
Note: Best practice in node js callback function would be, first argument
should return an error (null in case of no error) and then remaining arguments can be the return
values.
db_crud.js
var express = require('express');
var app = express();
var crud = require('./routes/crud_op_new.js');
var search = require('./routes/search.js');
var connection;
app.get('/search',(req,res)=>{
crud.connection(function (con) {
search.getuser(con,req.param('name'), function(err, result) {
if(err) {
res.status(501).send(err);
} else {
res.send(result);
}
});
});
});
app.listen(8003);
search.js
exports.getuser = function(connection,req,callback){
console.log("GET Request iniciated");
connection.query("select * from user,addr where name=? and user.id=addr.e_id",[req],(err,row)=>{
if(err){
callback("DB ERROR: "+err);
}
else {
if(row.length==0){
callback("No Records found");
}
else {
callback(null, row);
}
}
});
}

you call your function search.getuser(con,req.param('name'),result); ... result is not a function, it's undefined ... a callback needs to be a function so it can be called back
This should work
app.get('/search',(req,res)=>{
crud.connection(function (con) {
// vvvvvvvvvvvvvvv this is the callback function
search.getuser(con,req.param('name'),function(result) {
res.send(result);
});
});
});

Related

What would be necessary to code the callback function to receive the access token?

I am trying to retrieve the access token from an API (https://github.com/Axosoft/node-axosoft/)
To receive an access token we have to follow this process:
var axo = nodeAxosoft(axosoftUrl, credentials);
axo.Api.getLoginUrl(function(url) {
// open browser using authorizationUrl and get code parameter from
//redirected Url after login
var code = 'code received from redirect';
axo.Api.exchangeCodeForToken(code);
});
As I did not understood exactly how to get the code following that example nor what is the url parameter on getLoginUrl, I did it on my own.
I have a login route that redirects the user to the axosoft website for authentication and redirects the user to the /authorization-process route on my application.
On the /authorization-process I get the code returned by the login and call a function that should get the access token by calling:
axo.Api.exchangeCodeForToken(code);
Code:
var axosoft_code = req.query.code;
console.log(axosoft_code);
var token = request.exchangeAuthCodeForAccessToken(axosoft_code)
.then(function(token)
{
res.send(token);
})
The Method:
var connection = nodeAxosoft(client_url, credentials);
return new Promise(function(resolve, reject){
console.log("CODE: ", axosoft_code)
var token = connection.Api.exchangeCodeForToken(axosoft_code, function(token){
console.log(token);
resolve(token)
})
The problem is that returns null
I had a look at the API lib api.js and found that:
https://github.com/Axosoft/node-axosoft/blob/master/lib/api.js
function exchangeCodeForToken(code, callback) {
_credentials.code = code;
_access_token = '';
_authenticateCredentails(function (err) {
if (!err) {
callback(null, _access_token);
} else {
callback(err);
}
})
}
So I have two questions:
Does anyone has an Idea what am I doing wrong?
What would be necessary to code the callback function?
The method expects a callback function but I don't really know how to do it.
EDIT:
return new Promise(function(resolve, reject){
var token = connection.Api.exchangeCodeForToken(axosoft_code, function(response,err){
if(!err){
console.log("token",response)
resolve(token);
}
else{
console.log("error",err)
resolve(token);
}
});
})
OR
var token = connection.Api.exchangeCodeForToken(axosoft_code, function(response,err){
if(!err){
console.log("token",response.body)
return response.body;
}
else{
console.log("error",err)
return err;
}
});
I am giving to my callback function two args (response and err), my problem is that I am falling at the else condition.
The output of err is something similar to a token though the documentation here shows that it should be like that:
{
"error" : "invalid_request",
"error_description" : "One or more parameters are missing: client_secret"
}
Another point is that the page is frozen waiting for something to happen but nothing happens.
Given that this is the input:
function exchangeCodeForToken(code, callback) {
_credentials.code = code;
_access_token = '';
_authenticateCredentails(function (err) {
if (!err) {
callback(null, _access_token);
} else {
callback(err);
}
})
}
You should format your call as:
exchangeCodeForToken(axosoft_code, function(err, response) {
if (err) {
// Deal with error
} else {
// Deal with response
}
}
Node functions often pass through error variables first so that you have to receive them, which is considered good practice.

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);
});

NodeJS How to organize Callbacks in a controller

I am new to NodeJS and coming from a PHP environment I am trying to figure out how to work with multiple callbacks. I do understand the basics about callback and I think it does make sens when writing modules. My problem is when comes the time to use those modules how to organize all the callbacks. Below is my implementation a request reset password controller method (I am using SailsJS). This is a first draft of my code. It was mainly to test a method of organizing callbacks. What do you guys think of this structure ? Is there a better way do it?
var _ = require('lodash');
var moment = require('moment');
var mailer = require("../../services/Mailer");
var crypto = require('../../services/crypto');
var forms = require("forms"),
fields = forms.fields,
validators = forms.validators;
module.exports = {
// Request reset user password: submit form and send email
request_process : function(req, res, next) {
var form = createForm();
form.handle(req, {
// there is a request and the form is valid
// form.data contains the submitted data
success: function (form) {
var user = null;
var username = form.data.username;
User.findOne({'username' : username}, foundUser);
function foundUser( err, _user){
if(err)
res.send(500, 'User not found');
user = _user;
if user.isPasswordRequestNonExpired()
return res.view('user/resetting/passwordAlreadyRequested');
if !user.passwordRequestToken
user.passwordRequestToken = crypto.randomToken();
renderEmail(null, user);
}
function renderEmail(err, user){
res.render('email/resetting_check_email', {'user': user, }, sendEmail );
}
function sendEmail(err, template){
if(err)
return res.send(500, "Problem with sending email");
Mailer.send( user, "Reset Password", template, sentEmail);
}
function sentEmail(err, response){
if(err)
return res.send(500, "Error sending email");
user.passwordRequestedAt = moment().format();
user.save(finish);
}
function finish(err){
if(err)
return res.send(500);
res.view();
}
},
// the data in the request didn't validate,
// calling form.toHTML() again will render the error messages
error: function (form) {
console.log("registration error", form);
res.locals.form = form;
return res.render('user/registration/register');
},
// there was no form data in the request
empty: function (form) {
console.log("registration empty", form);
res.locals.form = form;
return res.render('user/registration/register');
}
},
// Tell the user to check his email provider
check_email : function(req, res, next) {
// if empty req.params.email
// redirect request view
// res.view('check_email.ejs')
},
// Reset user password
reset : function(req, res, next){
// find userByPasswordToken
// if !user
// res.view ('invalid or expired "confirmation token".')
// user.update password
// res.view('reset.ejs');
},
Node.js callback basics:
Most of the functions (Node and its Libraries (called modules)), are of asynchronous (async) nature.
These functions have a common signature with callback as the last argument: function(arguments.....callback).
The callback is just another JavaScript function. ( yes, in Javascript, functions can be passed around as arguments to other functions). Node.js typical callbacks have a signature with first argument as error (if one happened): callback(err,outputs......).
example: first argument is a string, second an object (defined inline) and the last is a function (defined inline).
doSomeWork('running',{doFast:true,repeat:20}, function(err,result){
if(err){
console.log('ohnoes!);
} else {
console.log('all done : %s',result);
}
});
which is equivalent to:
var type = 'running';
var options = {doFast:true,repeat:20};
var callback = function(err,result){
if(err){
console.log('ohnoes!);
} else {
console.log('all done : %s',result);
}
};
doSomeWork(type,options,callback);
So the basic contract here is give a function its arguments and pass a callback to be invoked, when it is done. The passed call back will be invoked some where in future when there is something to return, error or the results.
Multiple nested callbacks are generally less readable and complex:
function uploadAll(path,callback){
listFiles(path,function(err,files){
if(err){
callback(err);
}else{
var uploaded = [];
var error;
for(var i = 0 ; i < files.length; i++){
uploadFile(files[i],function(err,url){
if(err){
error = err;
break;
}else{
uploaded.push(url);
}
});
}
callback(error,uploaded);
}
});
};
But fortunately there are modules like async that help organize callbacks:
function uploadAll(path,callback){
async.waterfall(
[
function(cb){
listFiles(path,cb);
},
function(files,cb){
async.map(files,uploadFile,cb);
}
],callback);
}
Furthermore, there is a Promises pattern as well. Future versions support generators which provide many new async patterns.
you can use async or q to manage the callback pyramids

Cannot return values to response with mongoose/mongodb and nodejs

I am using Nodejs, ExpressJs, MongoDB via Mongoose. I have created a simple UserSchema . I have my code separated into multiple files because I foresee them getting complex.
The url '/api/users' is configured to call the list function in 'routes/user.js' which happens as expected. The list function of UserSchema does get called, but it fails to return anything to the calling function and hence no result goes out.
What am I doing wrong ?
I tried to model it based on http://pixelhandler.com/blog/2012/02/09/develop-a-restful-api-using-node-js-with-express-and-mongoose/
I think I am doing something wrong with the function definition of userSchema.statics.list
app.js
users_module = require('./custom_modules/users.js'); // I have separated the actual DB code into another file
mongoose.connect('mongodb:// ******************');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback() {
users_module.init_users();
});
app.get('/api/users', user.list);
custom_modules/users.js
function init_users() {
userSchema = mongoose.Schema({
usernamename: String,
hash: String,
});
userSchema.statics.list = function () {
this.find(function (err, users) {
if (!err) {
console.log("Got some data"); // this gets printed
return users; // the result remains the same if I replace this with return "hello"
} else {
return console.log(err);
}
});
}
UserModel = mongoose.model('User', userSchema);
} // end of init_users
exports.init_users = init_users;
routes/user.js
exports.list = function (req, res) {
UserModel.list(function (users) {
// this code never gets executed
console.log("Yay ");
return res.json(users);
});
}
Actually in your code you are passing a callback, which is never handled in function userSchema.statics.list
You can try the following code:
userSchema.statics.list = function (calbck) {
this.find(function (err, users) {
if (!err) {
calbck(null, users); // this is firing the call back and first parameter should be always error object (according to guidelines). Here no error, so pass null (we can't skip)
} else {
return calbck(err, null); //here no result. But error object. (Here second parameter is optional if skipped by default it will be undefined in callback function)
}
});
}
Accordingly, you should change the callback which is passed to this function. i.e.
exports.list = function (req, res){
UserModel.list(function(err, users) {
if(err) {return console.log(err);}
return res.json(users);
});
}

Categories

Resources