Node async.js: callback is not a function error? - node.js

I have this code:
async = require('async')
async.auto({
getUserName: function(callback) {
console.log('**In getUserName.**')
callback(null, 'Lem')
},
connectToDb: function(callback) {
console.log('**In connectToDb.**')
var connected = true
if(connected) {
callback(null, connected)
} else {
callback('Error connecting to DB.', null)
}
},
checkIfUserExist: [
'getUserName',
'connectToDb',
function(callback, results) {
console.log('**In checkIfUserExist.**',
JSON.stringify(results))
var userExist = false
if(userExist) {
callback('User exist in DB.')
} else {
setTimeout(
function() {
callback(null, userExist);
},
1000
);
}
}
],
signup: [
'checkIfUserExist',
function(callback, results) {
console.log('**In signup**', JSON.stringify(results))
var userName = results.getUserName
var isDbConnected = results.connectToDb
var userExist = result.checkIfUserExist
if(userName && isDbConnected && !userExist) {
callback(null,
{'status': '200', 'msg': 'Successfully signed up user'})
} else {
callback('Error signing up user.', null)
}
}
]
},
function(error, results) {
console.log('error = ', error)
console.log('results = ', results)
})
Why am I experiencing this error:
**In getUserName.**
**In connectToDb.**
error = function () {
if (fn === null) throw new Error("Callback was already called.");
var callFn = fn;
fn = null;
callFn.apply(this, arguments);
}
results = undefined
**In checkIfUserExist.** undefined
^[[A/home/lem/js/async/asyncAuto.js:30
callback(null, userExist);
^
TypeError: callback is not a function
at Timeout._onTimeout (/home/lem/js/async/asyncAuto.js:30:13)
at ontimeout (timers.js:365:14)
at tryOnTimeout (timers.js:237:5)
at Timer.listOnTimeout (timers.js:207:5)

There was a breaking change in async's auto method in v2, which you seem to use.
https://github.com/caolan/async/blob/master/CHANGELOG.md#breaking-changes
auto task functions now always take the callback as the last argument. If a task has dependencies, the results object will be passed as the first argument. To migrate old task functions, wrap them with _.flip

An async function, one that expects a callback as its last argument. Here is my working code.
var async = require('async');
async.auto({
getUserName: function(callback) {
console.log('**In getUserName.**')
callback(null, 'Lem')
},
connectToDb: function(callback) {
console.log('**In connectToDb.**')
var connected = true
if(connected) {
callback(null, connected)
} else {
callback('Error connecting to DB.', null)
}
},
checkIfUserExist: [
'getUserName',
'connectToDb',
function(results, callback) {
console.log('**In checkIfUserExist.**',
JSON.stringify(results))
var userExist = false
if(userExist) {
callback('User exist in DB.')
} else {
setTimeout(function() {
callback(null, userExist);
},1000);
}
}
],
signup: [
'checkIfUserExist',
function(results, callback) {
console.log('**In signup**', JSON.stringify(results))
var userName = results.getUserName
var isDbConnected = results.connectToDb
var userExist = results.checkIfUserExist
if(userName && isDbConnected && !userExist) {
callback(null,
{'status': '200', 'msg': 'Successfully signed up user'})
} else {
callback('Error signing up user.', null)
}
}
],
},
function(error, results) {
console.log('error = ', error)
console.log('results = ', results)
})
function(callback, results) should be function(results, callback)
Please check this url for reference.
https://caolan.github.io/async/docs.html#auto

Related

Callback function is not working as expected in watefall on async.foreachlimit

The callback function is not working as expected in a waterfall on async.for each limit.
When I remove that rest api call and if I call callback(null,arg2) it is working as expected, I think the problem with callback function or some api call in the below code.
var async = require("async");
var users = [1, 2, 3, 45]; // Initialize user array or get it from DB
var e = [];
var unirest = require("unirest");
var data = function() {
return new Promise((resolve, reject) => {
async.forEachLimit(
users,
1,
function(user, userCallback) {
async.waterfall(
[
function(callback) {
console.log(user);
callback(null, user);
},
function(arg1, callback) {
console.log(arg1);
callback(null, arg1);
},
function(arg2, callback) {
unirest
.get("http://dummy.restapiexample.com/api/v1/employee/1")
.end(function(response) {
if (response.error) callback("null", "data");
else callback(null, arg2);
});
}
],
function(err, result) {
if (err) {
console.log("err");
reject(e);
} else {
console.log("done", result);
e.push(result);
userCallback();
resolve(e);
}
}
);
},
function(err, result) {
console.log("User For Loop Completed", err, result);
}
);
});
};
I'm getting output as
expected outputs as

i am not getting any idea that where is error occured node js callback not function

in this function we get id from Mongo Database and process function to put varriable in GetID varriable
"callback is not function"
var GetID = function( nameval , callback ){
console.log(nameval);
console.log("munesh hello");
var result = GenerateID.find({ "id_name" : nameval },{"id_code":1 , "id_value":1 , "_id":0},function( err , genvalue ) {
if ( err )
{
console.log('error has been occured');
//throw err;
}
else {
if(genvalue === null)
{
callback( err , false );
}
else
{
console.log(genvalue);
//calling this function
callback( err , true );
}
}
// console.log(genvalue);
});
console.log('munesh kumar');
// console.log(result);
console.log('kumar');
};
When calling GetID, you are not sending 2 parameters (nameval and callback). You are only sending the first parameter:
var region_id = GenerateID.GetID( name );
Instead this is how you should call the function:
GenerateID.GetID(name, function(error, result) {
if(error) {
// handle error
} else {
if(!result) {
// not found
} else {
// do something with result
}
}
});
Remember that you are dealing with asynchronous functions. You cannot return output directly from an asynchronous function (GetID). Instead you have to pass it to the callback function.
Your GetID function should be something like this:
var GetID = function(nameval, callback) {
GenerateID
.find({ "id_name": nameval }, { "id_code": 1, "id_value": 1, "_id": 0 }, function(err, genvalue) {
if (err) {
callback(err);
} else {
if (genvalue === null) {
callback(null, null); // no document found
} else {
callback(null, genvalue);
}
}
});
};
var region_id = GenerateID.GetID( name , function(error, result) {
if(error) {
// handle 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');
}
}
});
get id function are below 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');
// callback(err);
} else {
if (genvalue === null) {
console.log('123');
callback(null, null); // no document found
} else {
console.log('456');
callback(null, genvalue);
}
}
});
};

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.

Callback function in Nodejs

I have function
var checkTokenIsExpired = function(name, token, response) {
LoginToken.find( { name: name, series: token }, function(error, info){
console.log("info: ", info[0]['expire']);
if (error) {
// response.send("error: %s}", error);
response(error);
}
if (info.length > 0) {
var expire = new String(info[0]['expire']);
// expire = expire.substr(0,26);
var date = new Date(expire);
if (date >= new Date()) {
// response.send("{info: success" );
response("success");
}
else{
// response.send("error: token-has-expired");
response("token-has-expired");
}
console.log("Response: ", info);
}
else {
response(null);
}
} );
}
To check token is expired or not? It will return a string.
And I call this function in here
exports.updateAccount = function(newData, callback)
{
Accounts.find({name:newData.body.name}, function(err, docs){
if (err) {
callback.send('{error: ' + String(err) + "}");
}
if (docs.length==0 || !docs) {
callback.send("{error: NULL }");
}
else {
checkTokenIsExpired(newData.body.name, newData.body.token, function(error, info){
if (error){
callback.send("{error: " + error + "}");
// I want to get info here }
console.log("check token: ", info);
// check info of token is expired or not
if (info!=null && info!="token-has-expired") {
var updateString = "";
if (newData.body.screen_name){
Accounts.update( {'name': newData.body.name},
{
"screen_name" : newData.body.screen_name
},
{ 'upsert' : true },
function (err, numberAffected, raw) {
if (err) return handleError(err);
});
}
if (newData.body.email){
Accounts.update( {'name': newData.body.name},
{
"email": newData.body.email
},
{ 'upsert' : true },
function (err, numberAffected, raw) {
if (err) return handleError(err);
});
}
if (newData.body.password == ''){
} else{
var password = encodePassword(newData.body.password, docs[0]['salt']);
Accounts.update( {'name': newData.body.name},
{
"hassedPass" : password,
},
{ 'upsert' : true },
function (err, numberAffected, raw) {
if (err) return handleError(err);
});
}
}
});
}
I want to get the info when call checkTokenIsExpired but when I console.log("info", info) it return undefined.
in checkTokenIsExpired, you need to pass info to the response callback otherwise it is not in scope of your second code.
at least in the case where you have success:
response("success", info);
Instead of passing "success", you'd typically pass null to indicate there is no error.
I have solved problem
checkTokenIsExpired(newData.body.name, newData.body.token, function(error, info)
because it will take 1 parameter but I put 2
Change it into checkTokenIsExpired(newData.body.name, newData.body.token, function(info)
It will correct :D

Resources