Weird Error Occurred During Function Run - javascript

I have the following function :
var appendStructure = {
init : function(wrapper,structure,cls,callback) {
$(wrapper).appendTo(container).hide()
var object = $(container).find(cls);
$(structure.join('')).appendTo(object);
showObj(object,function() {
if(opts.centerObj == true) {
$(window).resize(function() {
var cssProps = getProps(object);
object.css(cssProps);
});
}
if(typeof callback == 'function') {
callback();
}
});
}
}
And the other functions that are called within it:
var getProps = function(obj) {
return {
'position' :'absolute',
'top' : (($(window).height() - $(obj).outerHeight()) / 2)+'px',
'left' : (($(window).width() - $(obj).outerWidth()) / 2)+'px'
}
}
var showObj = function(obj,callback) {
return setTimeout(function () {
if(opts.centerObj == true) {
var cssProps = getProps(obj);
obj.css(cssProps).fadeIn('slow');
}
else {
obj.fadeIn('slow');
}
if(typeof callback == 'function') {
callback();
}
}, 1500);
}
And I run the function like this:
if(appendStructure.init(wrapper.login,structure.login,'.content-login')){
console.log('Object Appended');
}
else {
console.log('Error');
}
My question is, why is the console outputting Error, because the function actually works and everything that is suppose to happen, happens ?

appendStructure.init does not return any value, hence the return value will be undefined. undefined evaluates to false, so the else branch of your if...else statement is executed.

Related

TypeError: cb is not a function

I'm stuck. I keep getting the same cb is not a function error. Here's my error:
TypeError: cb is not a function
I just started learning javascript a few days ago, so I'm very new. I'm simply watching youtube videos that do what I need done for my application and I write what they write. So far it's been going well, had a few problems that I managed to fix on my own. But this one I can't figure out. So a little help would be very much appreciated.
var isValidPassword = function(data,cb) {
db.users.find({username:data.username,password:data.password},function(err,res) {
if (res.length > 0) {
return cb(true);
} else {
return cb(false);
}
});
}
var isUsernameTaken = function(data,cb) {
db.users.find({username:data.username},function(err,res) {
if (res.length > 0) {
return cb(true);
} else {
return cb(false);
}
});
}
var addUser = function(data,cb) {
db.users.insert({username:data.username,password:data.password},function(err) {
return cb();
});
}
io.on('connection', (sock) => {
sock.id = Math.random();
SOCKET_LIST[sock.id] = sock;
console.log('someone connected');
sock.on('signIn', function(data) {
if (isValidPassword(data)) {
sock.emit('signInResponse', {success:true});
} else {
sock.emit('signInResponse', {success:false});
}
});
sock.on('signUp', function(data) {
if (isUsernameTaken(data)) {
sock.emit('signUpResponse', {success:false});
} else {
addUser(data);
sock.emit('signUpResponse', {success:true});
}
});
});
I keep getting this error:
TypeError: cb is not a function
at C:\Users\user\Desktop\Mekkie\mekkie\testlogin.js:32:19
at C:\Users\user\Desktop\Mekkie\mekkie\node_modules\mongojs\lib\cursor.js:73:24
at AsyncResource.runInAsyncScope (async_hooks.js:188:21)
at runInAsyncScope (C:\Users\user\Desktop\Mekkie\mekkie\node_modules\mongojs\lib\cursor.js:195:16)
at C:\Users\user\Desktop\Mekkie\mekkie\node_modules\mongojs\lib\cursor.js:205:5
at handleCallback (C:\Users\user\Desktop\Mekkie\mekkie\node_modules\mongojs\node_modules\mongodb\lib\utils.js:120:56)
at C:\Users\user\Desktop\Mekkie\mekkie\node_modules\mongojs\node_modules\mongodb\lib\cursor.js:683:5
at handleCallback (C:\Users\user\Desktop\Mekkie\mekkie\node_modules\mongojs\node_modules\mongodb-core\lib\cursor.js:171:5)
at setCursorNotified (C:\Users\user\Desktop\Mekkie\mekkie\node_modules\mongojs\node_modules\mongodb-core\lib\cursor.js:515:3)
at C:\Users\user\Desktop\Mekkie\mekkie\node_modules\mongojs\node_modules\mongodb-core\lib\cursor.js:599:16
Welcome to Stackoverflow, the cb is usually referred as callback function to pass to another function, I think in your code you don't need this. Probably you referenced the code from the documentation of Socket.io or MongoDB where they often use to pass a callback function as result.
I see from your code that you just need to pass true/false as result of db operation, so just remove the cb parameter from your functions and return just true/false:
var isValidPassword = function(data) {
db.users.find({username:data.username,password:data.password},function(err,res) {
if (res.length > 0) {
return true;
} else {
return false;
}
});
}
var isUsernameTaken = function(data) {
db.users.find({username:data.username},function(err,res) {
if (res.length > 0) {
return true;
} else {
return false;
}
});
}
var addUser = function(data) {
db.users.insert({username:data.username,password:data.password},function(err) {
if (err) {
return false;
} else {
return true;
}
});
}

Javascript - continue foreach

I have a piece of code:
var a = false;
function wait(milliseconds, async) {
if(!async) {
setTimeout(function() {
console.log('Sync timer done.');
a = true;
return true;
}, milliseconds*1000);
}
(...)
f_recipe.forEach(function(item, index) {
if (obj['actual_step'] != 0 && obj['actual_step'] != index ) {
e = "Desync";
throw e;
};
console.log("Step: " + obj.actual_step);
if(item.substr(item.length - 6) != "false)"){
if (eval(item)) {
obj['actual_step']++;
}
} else {
eval(item);
var ival = setInterval(function(){
if(a) {
console.log('do the next thing');
clearInterval(ival);
}
}, 1000);
}
});
But when I get to 'do the next thing'(interval complete), the forEach loop doesn't continue to the next element of the array. 'a' is set to true after timeout (kind of a synchronous wait in JS). f_recipes is a string array with function call (e.g. 'wait(20, false)').
How to get it to work?
What you're trying to do seems like a very bad idea, but promises can help with this (using Bluebird here because it provides Promise.delay and Promise.each):
function wait(seconds, dontActuallyWait) {
return dontActuallyWait ? null : Promise.delay(seconds * 1000);
}
function runSequence(things) {
return Promise.each(things, function(thing) {
return eval(thing);
});
}
runSequence([
'console.log("hello")',
'wait(2, false)',
'console.log("hello again")',
'wait(5, false)',
'console.log("goodbye")'
]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.5.1/bluebird.min.js"></script>

How to return a value from async for JQuery Validator

Using the async module for JS, I need to retrieve values from two functions running in parallel and then use them on a callback that returns a final true/false value.
There seems to be a problem with the async scope, since I can't retrieve the return value from the callback. Any ideas on how to do this?
This is the code. It's basically a validator for received values:
$.validator.addMethod('verifySystem', function (value, element) {
var data = value.split(':');
var respuesta;
async.series([
function (callback) {
if( data.length === 3){
// is this format the correct one?
if ((data[1] == 'testi' || data[1] == 'tes') && data[2].length == 6 && data[0].length == 7){
callback(null, 'ok');
} else {
callback('Error in format',null);
}
} else {
callback('Error in format', null);
}
},
function (callback) {
// does the document exist?
var ajaxverify = function() {
return $.ajax({
url: 'db_test/' + value
});
};
ajaxverify()
.done(function(result) {
callback(null, 'ok');
})
.fail(function(error) {
callback('not_found', null);
});
}
],
function (errors, results) {
if (errors){
return false;
} else {
return true;
}
});
}, "error message");

How can I include a function (and its parameter) within an event handler, without the function being called on page load?

I am refactoring this code
$("#one").on("click", function() {
if(operator === undefined) {
firstArray.push("1");
}
else {
secondArray.push("1");
}
});
$("#two").on("click", function() {
if(operator === undefined) {
firstArray.push("2");
}
else {
secondArray.push("2");
}
});
$("#three").on("click", function() {
if(operator === undefined) {
firstArray.push("3");
}
else {
secondArray.push("3");
}
});
$("#four").on("click", function() {
console.log("4");
if(operator === undefined) {
firstArray.push("4");
}
else {
secondArray.push("4");
}
});
$("#five").on("click", function() {
console.log("5");
if(operator === undefined) {
firstArray.push("5");
}
else {
secondArray.push("5");
}
});
$("#six").on("click", function() {
console.log("6");
if(operator === undefined) {
firstArray.push("6");
}
else {
secondArray.push("6");
}
});
$("#seven").on("click", function() {
console.log("7");
if(operator === undefined) {
firstArray.push("7");
}
else {
secondArray.push("7");
}
});
$("#eight").on("click", function() {
console.log("8");
if(operator === undefined) {
firstArray.push("8");
}
else {
secondArray.push("8");
}
});
$("#nine").on("click", function() {
console.log("9");
if(operator === undefined) {
firstArray.push("9");
}
else {
secondArray.push("9");
}
});
$("#zero").on("click", function() {
console.log("0");
if(operator === undefined) {
firstArray.push("0");
}
else {
secondArray.push("0");
}
});
into this
function pushNumber(numberToPush) {
if(operator === undefined) {
firstArray.push(numberToPush);
}
else {
secondArray.push(numberToPush);
}
}
$("#one").on("click", pushNumber("1"));
$("#two").on("click", pushNumber("2"));
$("#three").on("click", pushNumber("3"));
$("#four").on("click", pushNumber("4"));
$("#five").on("click", pushNumber("5"));
$("#six").on("click", pushNumber("6"));
$("#seven").on("click", pushNumber("7"));
$("#eight").on("click", pushNumber("8"));
$("#nine").on("click", pushNumber("9"));
$("#zero").on("click", pushNumber("0"));
When I try the above code, the pushNumber function is being called on page load. I understand that this is happening because I have put parentheses, thereby calling the function. But I do not know how I can pass a parameter to the function without doing it this way.
I'd appreciate some help, thanks.
What you want to do is "curry" a function, or generate a new function that already has some arguments added into it.
First, we'll make a function to generate a new function for each click handler:
function generateHandler(argument) {
return function() {
pushNumber(argument);
};
}
Then, you can use it like this:
$("#one").on("click", generateHandler("1"));
What you want is something called partial application or currying. You can do it manually for your case with a higher-order function, like this:
function pushNumber(numberToPush)
return function() {
if(operator === undefined) {
firstArray.push(numberToPush);
} else {
secondArray.push(numberToPush);
}
};
}
But many utiility libraries also offer a curry or partial function that you might be able to use to wrap your function.

How do I block a dialog("open") call with jQuery/UI's Dialog

I'm trying to create a function that shows a modal dialog which when called blocks until the dialog is closed, this will allow for a result to be returned to the caller
The following function is an attempt which has two problems.
It returns the result while the dialog is still open.
The selector test does not find the dialog, inspecting with firebug reveals that the id element is lost once the dialog is created.
.
function getCountrySelection() {
var ctryCode;
var dlg = $("#JS-field-dlg-ctry-select");
if (dlg.size() === 0) {
dlg = $("<div id='JS-field-dlg-ctry-select' title='Select Country' class='dialog-fields'></div>");
dlg.append("Customer found in both Australia and New Zealand");
dlg.dialog({
autoOpen: false,
width: 400,
height: 160,
modal: true,
buttons: {
"Australia": function() {
ctryCode = "au";
$(this).dialog("close");
},
"New Zealand": function() {
ctryCode = "nz";
$(this).dialog("close");
},
"Cancel": function() {
$(this).dialog("close");
}
}
});
}
dlg.dialog('open');
return ctryCode;
}
EDIT: I thought I'd show how I'm calling this:
buttons: {
"Find": function() {
var custAu = JS.sales.getCustomer("au", inpCust.val());
var custNz = JS.sales.getCustomer("nz", inpCust.val());
var cust;
if (custAu === undefined && custNz === undefined) {
alert('No customer could be found with that number.');
return;
} else if (custAu !== undefined && custNz !== undefined) {
var ctry;
getCountrySelection(function(result) {
ct = result;
});
if (ctry === "au") {
cust = custAu;
} else if (ctry === "nz") {
cust = custNz;
} else {
return;
}
} else if (custNz === undefined) {
cust = custAu;
} else {
cust = custNz;
}
if (cust) {
$(this).dialog("close");
// Do something with cust.
} else {
alert('Customer could not be found.');
}
},
"Cancel": function() {
$(this).dialog("close");
}
}
There is no way to block execution until the dialog closes; JavaScript does not allow to "suspend" execution. Your best bet is to change the contract of your function; instead of returning the value straight away, it should accept a callback function that it will call with the result as soon as the dialog is dismissed. Then the code calling this will provide a suitable callback in which it can continue its execution.
Something like this:
function getCountrySelection(callback) {
(...)
buttons: {
"Australia": function() {
$(this).dialog("close");
callback("au");
},
"New Zealand": function() {
$(this).dialog("close");
callback("nz");
},
"Cancel": function() {
$(this).dialog("close");
callback();
}
}
});
}
dlg.dialog('open');
}
Then use:
getCountrySelection(function(result) {
if (result) {
...handle result...
} else {
...the user cancelled the dialog...
}
});
This is basically the same thing as with AJAX calls; you can't "suspend" your AJAX call to wait until the AJAX actually completes and returns the result, hence "asynchronous".
EDIT: In your specific example, you could use it like this:
buttons: {
"Find": function() {
var custAu = JS.sales.getCustomer("au", inpCust.val());
var custNz = JS.sales.getCustomer("nz", inpCust.val());
if (custAu === undefined && custNz === undefined) {
alert('No customer could be found with that number.');
return;
} else if (custAu !== undefined && custNz !== undefined) {
getCountrySelection(function(ctry) {
var cust;
if (ctry === "au") {
cust = custAu;
} else if (ctry === "nz") {
cust = custNz;
}
handleCustomer(cust);
});
} else if (custNz === undefined) {
handleCustomer(custAu);
} else {
handleCustomer(custNz);
}
function handleCustomer(cust) {
if (cust) {
$(this).dialog("close");
// Do something with cust.
} else {
alert('Customer could not be found.');
}
}
},
"Cancel": function() {
$(this).dialog("close");
}
}

Categories