ExpressJS - function returning undefinded - node.js

function checkFamilyStatus() keeps returning undefined for some reason, when it should be returning a boolean value from a mongodb collection.
A bit of context here - I decided to separate the logic part from the router methods like get and post methods, so as to make it look clean and understandable like in functional programming. So I put the logic part in functions and invoke them inside the router methods, but it doesn't work out. Besides, I don't know if this is a good practice or not. Wouldn't it be much easier to read if done like this, instead of say, putting a whole bunch of code in one place?
I've been stuck on this piece of code for a while. I am a bit confused on the working of asynchronous JS as a whole. I did some research, but still don't understand why this wouldn't work. Could someone clarify this up for me?
// post method
router.post("/create", ensureAuthenticated, async(req, res) => {
let userID = req.user.id;
console.log(await checkFamilyStatus(userID)); // but returns undefined
// rest of the code
}
// check family status
checkFamilyStatus = async userID => {
Account.findOne({
_id: userID
}, (err, account) => {
return account.hasFamily; // should return boolean value ?
});
};

Assuming the logic behind account.hasFamily is correct, then you need to await for the return, so it should be return await account.hasFamily;

Related

Retrieving a value in a function in Node.js

I'm struggling with callbacks in Node.js. I simply want playerNumber to be set to the number of players in my collection of Players. The console.log works, but I can't get the variable out of the function and into the playerNumber variable.
And if there's a simpler way get this value for use in the rest of my backend code, I'm all ears. I'm clearly new at Node.js, but the code always seems more involved than I'm expecting.
Thanks in advance!
var playerNumber = function countPlayers(callback){
Player.count(function(err, numOfDocs) {
console.log('I have '+numOfDocs+' documents in my collection');
callback(err, numOfDocs);
});
}
It's probably async, and it's a typical first-timer experience to want to "get back to normal" on the call chain on the way back from async call. This can't be done, but it's not so bad to live with it. Here's how...
Step 1: Promises are better than callbacks. I'll leave the long story
to others.
Step 2: Callbacks can be made into promises
In the OP case...
// The promise constructor takes a function that has two functions as params
// one to call on success, and one to call on error. Instead of a callback
// call the 'resolve' param with the data and the 'reject' param with any error
// mark the function 'async' so callers know it can be 'await'-ed
const playerNumber = async function countPlayers() {
return new Promise((resolve, reject) => {
Player.count(function(err, numOfDocs) {
err ? reject(err) : resolve(numOfDocs);
});
});
}
Step 3: Yes, the callers must deal with this, and the callers of the callers, and so on. It's not so bad.
In the OP case (in the most modern syntax)...
// this has to be async because it 'awaits' the first function
// think of await as stopping serial execution until the async function finishes
// (it's not that at all, but that's an okay starting simplification)
async function printPlayerCount() {
const count = await playerNumber();
console.log(count);
}
// as long as we're calling something async (something that must be awaited)
// we mark the function as async
async function printPlayerCountAndPrintSomethingElse() {
await printPlayerCount();
console.log('do something else');
}
Step 4: Enjoy it, and do some further study. It's actually great that we can do such a complex thing so simply. Here's good reading to start with: MDN on Promises.

How to pass data in a promise chain, I am using sequelize

I am really struggling here. Admittedly I am no guru especially when it comes to node and asynchronous programming, I am an old C# .net developer so I am comfortable with code but struggling here.
Here's the back story, short and sweet. I have a pg database and I am using the sequelize ORM tools to create a relatively simple CRUD app.
Here's what I want to do.
Make a call to the findAll function on one object.
I need a piece of information from that first call so that I can make a subsequent call.
For instance. Lookup the current user to get their details, grab their ID and now lookup their display preferences.
I know I can run two requests that are not linked using Promise.all, here is an example of this already working.
var delConfig = deliverabiltyConfigs.findAll2(req.signedCookies.tsUser);
var delPack = deliverabilityPackages.findAll2();
Promise.all([delConfig, delPack]).then((results) =>{
res.render('index', { title: 'Deliverability Calculator', UserEmail : req.signedCookies.tsUser, UserName : req.signedCookies.tsUserName, data:results[0], packs:results[1]});
});
Where I am stuck is passing data from one promise to then next and needing them to run asynchronously.
Please help!
There are a few way you can do this. Either use promise chaining or with async & await.
Promise chaining might be the simplest way to do this now, but I would suggest using async await as its easier to read. Since you didn't really provide a sample of what you were trying to do I will make something generic that should hopefully help.
So using promise chaining you would do something like:
pgConnection.findAll().then((data) => {
const foo = data.foo;
pgConnection.findSomething(foo).then((data2) => {
console.log(data2);
});
});
What is happening here is once the promise from findAll() is resolved successfully it will call the .then method and will pass the resulting data there for you to use in your next db query and then I am just printing out the result of the final db query.
This is how you could do it using async & await:
async function getFoo() {
const data = await pgConnection.findAll();
const foo = data.foo;
const data2 = await pgConnection.findSomething(foo);
console.log(data2);
}
The await keyword can only be used inside of an async function so it might not be as simple to change as just using a .then promise chain.

pass result from AwaitReactions out of function discord.js

I am new to async functions. I want to utilize the code below to ask the user a question and react to the question with an X or check mark to get the users answer on whether or not to delete something to make room for a new entry.
The function below works perfectly fine. However, I want to pass the result from the function out of the function so I can make an if else statement outside of it and that is where I am stuck.
I've looked around online and saw several things related to callbacks being used, but each example I've seen is different for something I think is similar, so I am just confused. And none of these examples have been used for Reactions on Discord, so I'm just not sure where to go.
const agree = "✅"
const disagree = "❌"
let msg = await message.author.send("You have made the maximum number of decks. Would you like to delete one of your decks in order to make a new one? Please react with one of the following...")
await msg.react(agree)
await msg.react(disagree)
const filter = (reaction, user) => {
return ['✅', '❌'].includes(reaction.emoji.name) && user.id === message.author.id;
};
const reactions = await msg.awaitReactions(filter, {
max: 1
}).then(collected => {
const result = collected.last();
})
return result;
}
deleteDeckQuestion(function(result){
console.log(result)
}).catch(err => console.error(err))
The above code results in 'undefined' being logged to the console when I run deleteDeckQuestion. No errors otherwise. I would like it to make the Results variable accessible to me outside the function so I can make an if else statement based upon which reaction the user added to the question.
I tried putting the if else statement I wanted to use with the results of deleteDeckQuestion inside the async function and it operated fine, but then inside the "Yes" result of that function, I want to put another Async function to ask which deck 1, 2 or 3 should be deleted and have the same reaction-determines-answer-to-question scenario. Just saves the user typing more than necessary at the ease of mobile users.
Would it be easier I just put an async function inside another async function? Something tells me that isn't the best idea in terms of efficiency. Eventually these reactions will lead to using mysql queries, which I am comfortable with using, but it will get pretty lengthy and functions inside other functions just seems like a mess... not sure if that is part of the "callback hell" I've read the joys of though...
Thanks for any help in advance.
collected within your then() callback and reactions are the exact same object. However, result's scope is limited to within the callback.
In this example code, collected is the result of msg.awaitReactions(...)'s fulfilled promise. Then, result is declared in the same scope, and therefore accessible where you need it to be.
const collected = await msg.awaitReactions(filter, { max: 1 })
.catch(console.error);
const result = collected.first();
MDN: Async Programming, await, then(), scope
Discord.js: Message.awaitReactions()

How to return promise to the router callback in NodeJS/ExpressJS

I am new to nodejs/expressjs and mongodb. I am trying to create an API that exposes data to my mobile app that I am trying to build using Ionic framework.
I have a route setup like this
router.get('/api/jobs', (req, res) => {
JobModel.getAllJobsAsync().then((jobs) => res.json(jobs)); //IS THIS THe CORRECT WAY?
});
I have a function in my model that reads data from Mongodb. I am using the Bluebird promise library to convert my model functions to return promises.
const JobModel = Promise.promisifyAll(require('../models/Job'));
My function in the model
static getAllJobs(cb) {
MongoClient.connectAsync(utils.getConnectionString()).then((db) => {
const jobs = db.collection('jobs');
jobs.find().toArray((err, jobs) => {
if(err) {
return cb(err);
}
return cb(null, jobs);
});
});
}
The promisifyAll(myModule) converts this function to return a promise.
What I am not sure is,
If this is the correct approach for returning data to the route callback function from my model?
Is this efficient?
Using promisifyAll is slow? Since it loops through all functions in the module and creates a copy of the function with Async as suffix that now returns a promise. When does it actually run? This is a more generic question related to node require statements. See next point.
When do all require statements run? When I start the nodejs server? Or when I make a call to the api?
Your basic structure is more-or-less correct, although your use of Promise.promisifyAll seems awkward to me. The basic issue for me (and it's not really a problem - your code looks like it will work) is that you're mixing and matching promise-based and callback-based asynchronous code. Which, as I said, should still work, but I would prefer to stick to one as much as possible.
If your model class is your code (and not some library written by someone else), you could easily rewrite it to use promises directly, instead of writing it for callbacks and then using Promise.promisifyAll to wrap it.
Here's how I would approach the getAllJobs method:
static getAllJobs() {
// connect to the Mongo server
return MongoClient.connectAsync(utils.getConnectionString())
// ...then do something with the collection
.then((db) => {
// get the collection of jobs
const jobs = db.collection('jobs');
// I'm not that familiar with Mongo - I'm going to assume that
// the call to `jobs.find().toArray()` is asynchronous and only
// available in the "callback flavored" form.
// returning a new Promise here (in the `then` block) allows you
// to add the results of the asynchronous call to the chain of
// `then` handlers. The promise will be resolved (or rejected)
// when the results of the `job().find().toArray()` method are
// known
return new Promise((resolve, reject) => {
jobs.find().toArray((err, jobs) => {
if(err) {
reject(err);
}
resolve(jobs);
});
});
});
}
This version of getAllJobs returns a promise which you can chain then and catch handlers to. For example:
JobModel.getAllJobs()
.then((jobs) => {
// this is the object passed into the `resolve` call in the callback
// above. Do something interesting with it, like
res.json(jobs);
})
.catch((err) => {
// this is the error passed into the call to `reject` above
});
Admittedly, this is very similar to the code you have above. The only difference is that I dispensed with the use of Promise.promisifyAll - if you're writing the code yourself & you want to use promises, then do it yourself.
One important note: it's a good idea to include a catch handler. If you don't, your error will be swallowed up and disappear, and you'll be left wondering why your code is not working. Even if you don't think you'll need it, just write a catch handler that dumps it to console.log. You'll be glad you did!

How does Express/Connect middleware work?

I am learning Node.js, and I have read some tutorials, like The Node Beginner Book for learning the core funcionality. But the more I read some examples, the more doubts I start collecting.
On the further example, obtained from a tutorial, we can see that for a CRUD 'read' request for key /documents/titles.json, we are returning a value:
app.get('/documents/titles.json', loadUser, function(req, res) {
Document.find({ user_id: req.currentUser.id },[], { sort: ['title', 'descending'] },
function(err, documents) {
res.send(documents.map(function(d) {
return { title: d.title, id: d._id };
}));
});
});
On this example, the function loaduser() is used for authentication purposes:
function loadUser(req, res, next) {
if (req.session.user_id) {
User.findById(req.session.user_id, function(err, user) {
if (user) {
req.currentUser = user;
next();
} else {
res.redirect('/sessions/new');
}
});
}
}
What I don't understand is:
I suppose that node.js, before start executing the app.get, it goes to loaduser function. loadUser() function has three parameters: req,res,next, but I don't see, at least, how you pass from app.get() the "req" parameter to loadUser(). From where does it come?
Inside loadUser() function, when you execute next(), it means that the function app.get()" can continue its procedure, but this req.currentUser = user, is the same req that is used on app.get() function?
Inside loadUser() function, when you execute res.redirect() code, automatically breaks the procedure on app.get() function, right? it looks like it doesn't return to Document.find().
The questions you've asked are about the Express framework internals specifically:
When you call app.get(route, loadUser, final) Express will make a stack (array) with the loadUser and final function functions and it will know that when you call next it should execute the following function in the stack with the same req and res params.
When you call next it will just pass to the next function in the middleware stack.
Since you call res.redirect and you don't call return, it won't pass to the next function in the stack (the one with Document.find).
Resources:
http://howtonode.org/getting-started-with-express
I think in order to be comfortable with this you need get familiar with idea of middleware and how it's used in connect framework.
I've found few articles where this subject explained well enough. Take a look there:
http://howtonode.org/connect-it
and here http://stephensugden.com/middleware_guide/
the main idea is you have a set of layers and each time when new request arrives it goes through each level and on each level you can decide what to do with that. You can stop at some level, do something and return response or you can pass it to the next layer

Resources