Nodejs - Cannot read property then of undefined - node.js

I'm getting this error when executing the following code:
getAggregatedRatings(query).then(ratings=>{
if(ratings){
return res.json(ratings);
}else{
return res.send(200);
}
}).catch((error)=>{
return res.send(500);
});
function getAggregatedRatings(query){
movieRating.aggregate(query)
.exec((err, ratings)=> {
if (err || !ratings) {
return Promise.reject(err);
}
else {
return Promise.resolve(ratings);
}
});
}
Please note that 'getAggregatedRatings' returns the query results as expected.
Please advise what I'm doing wrong.

Your getAggregatedRatings function is not returning a promise, or anything for that matter, which explains why when trying to access it, the result is undefined.
Try changing it to this:
function getAggregatedRatings(query){
return new Promise((resolve, reject) => {
movieRating.aggregate(query)
.exec((err, ratings)=> {
if (err || !ratings) {
reject(err);
}
else {
resolve(ratings);
}
});
})
}

It appears you may be using mongoose for this query. If you're using a recent version of mongoose, then .exec() already returns a promise so you can avoid the promise anti-pattern of wrapping one promise in a manually created new promise whereas you can instead just use the promise it already returns:
function getAggregatedRatings(query){
return movieRating.aggregate(query).exec().then(result => {
if (!result) {
throw new Error("no results found");
}
});
}

Related

async function resolve with Promise but returns undefined

I'm reading data from db with using await so I used Promise but the function seems to return nothing
async function read() {
return new Promise((resolve, reject) => {
const db = new DB();
db
.read()
.then(result => {
resolve(result);
}).catch(() => {
reject('db-error');
});
});
}
(async () => {
const data = await read();
console.log(data); // undefined
})();
How can I make read() return result?
You are making it more complicated than it has to be. If you are already using an API that returns a promise then there is no need to use the promise constructor yourself.
And declaring a function as async is only necessary if you are using await in it to deal with promises.
So either do:
function read() {
const db = new DB();
return db
.read()
.catch(() => {
return 'db-error';
});
}
Or
async function read() {
const db = new DB();
try {
return await db.read();
} catch(error) {
return 'db-error';
}
}
If you are still not getting the value you want then you are not using the database API correctly and you have to read its documentation to figure out how to get back the right data.
The awesome guys who write the MDN Web Docs say that the result of await will be undefined if the promise that is being waited on is rejected: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#handling_rejected_promises
Check out the following scenario.
This is a simple function that returns a Promise:
function asyncFunc(waitTime) {
return new Promise((resolve, reject) => {
setTimeout(() => {
// say we prefer people who do things in 3 seconds or less
if (waitTime <= 3000) {
resolve('Promise resolved! You\'re fast! :)');
} else {
reject('Promise rejected! You\'re slow! :(');
}
}, waitTime);
});
}
Let's test the function using a method similar to yours:
async function testAsyncFunc(waitTime) {
try {
const result = await asyncFunc(waitTime);
console.log(result);
} catch(error) {
console.error(error.message);
}
}
testAsyncFunc(3000); // Returns `Promise resolved! You're fast! :)`, as expected
testAsyncFunc(3001); // Returns `undefined` instead of `Promise rejected! You're slow! :(`
But since we want the actual rejection error of the asynchronous operation instead of undefined, the solution is to chain catch to the await statement to catch any rejection errors immediately you call the asynchronous function and then throw the error so it can be caught by any catch error handler you may want to use, like so:
async function testAsyncFunc(waitTime) {
try {
const result = await asyncFunc(waitTime)
.catch(error => {
// throw the rejection error so it can be handled by the catch block below
throw new Error(error);
});
// if no errors
console.log(result);
} catch(error) {
console.error(error.message);
}
}
testAsyncFunc(3001); // Returns the expected result: `Promise rejected! You're slow! :(`

nodejs arrow function not returning expected value

I'm using the aws-sdk to upload a message to kinesis. It works fine but i'm trying to solve for when the action does not work (due to internet being down or something).
Here is the code i'm running.
const returnValue = kinesis.putRecord(params, (err, data) => {
if (err) {
logger.info(err);
return err;
} else {
logger.info(data);
return data;
}
});
console.log(returnValue);
I expect to get back the err or data. Instead what I get back is a Huge json of what I assume is the kinesis.PutRecord request itself.
Any ideas on why i'm not getting data returned to my returValue variable?
The console logs data and error just fine.
UPDATE:
as pointed out in the comments, I needed to wrap the function in a promise. I also put it in a try catch since if you throw a "reject" without a catch you get an unhandled promise rejection.
Updated code here:
try {
const returnValue = await new Promise(function(resolve, reject){
kinesis.putRecord(params, (err, data) => {
if (err) {
logger.info(err);
reject(err);
} else {
logger.info(data);
resolve(data);
}
});
});
logger.log(returnValue);
} catch (error) {
logger.error(error);
return error;
}

How to return responses in nodejs?

I have below code:
exports.generateCo = async function(req,res,next){
//some code
return new Promise(function (resolve,reject){
if(err){
//some code
}
else{
//some code
let mail = await sendEmail.otp(val,mailid,sub);
console.log("mail -- ",mail);
}
})
}
In Another file:
exports.otp = async function(val,mailid,sub){
//some code
transporter.sendMail(options,(error,info) =>
if(error){
//error logs
respobj = {status: "err"};
}
else{
//success logs
respobj = {status: "success"};
}
return respobj;
}
Here in the first file, Im not able to get the response in "mail" variable. Im getting "undefined" value. Can anybody please help me with this?
The await wont work inside a promise.
As per the given code,you do not need to define a new promise inside the async function.
If you need the new promise, you cannot you the await inside a promise callback. You should the then format instead.
sendEmail.otp(val,mailid,sub).then((mail) => {
console.log("mail -- ",mail);
})
Also, the otp function has a callbck, so it has to be wrapped in a
promise.
exports.otp = async function(val,mailid,sub) {
//some code
return new Promise((resolve, reject) = {
transporter.sendMail(options,(error,info) => {
if(error){
//error logs
respobj = {status: "err"};
} else {
//success logs
respobj = {status: "success"};
}
return resolve(respobj);
})
})
}
Is the final return in right spot? That's usually what I find I made a mistake.
Make call back function as async then use await.
Return respobj from with in call back, if you try to return the response from outside of the callback then before waiting for any transporter.sendMail it will return undefined.
exports.generateCo = async function(req,res,next){
//some code
return new Promise(async function (resolve,reject){
if(err){
//some code
}
else{
//some code
let mail = await sendEmail.otp(val,mailid,sub);
console.log("mail -- ",mail);
}})
}
exports.otp = async function(val,mailid,sub){
//some code
transporter.sendMail(options,(error,info) => {
if(error){
//error logs
respobj = {status: "err"};
}
else{
//success logs
respobj = {status: "success"};
};
return respobj});
}

Node Js call back / promise/ return

I am kind of new to this node js and went through many explanations, tried many solutions but still cant get my head wrapped around the function call backs.
//app.js file
var dashboardfunc = require('./models/admindashboard');
app.get("/dashboard/:id?", function(req, res) {
console.log("we are here in dashboard")
var data = {id: req.params.id};
console.log(data)
dashboardfunc.productlist().then(function(results){
console.log("i am here now ....")
console.log(results)
}).catch(function(err){
if(err){
console.log(err)
}
})
});
//admindashboard.js file
//I tried many other alterations like using call back etc.
// i want the damn results to be back to the app.js and use that
//
function productlist(data) {
return new Promise(function(resolve, reject) {
var param = [data.id];
var sql = 'select * from product where seller_id=?';
console.log(param)
pool.query(sql, param, function(err, results) {
if (err) {
console.log(err)
}
else {
if (results === undefined) {
reject(new Error("Error rows is undefined"));
}
else {
console.log("we got here in productlist")
console.log(results)
return results;
}
}
})
})
}
module.exports = productlist;
<--Result -->
Rb-v2 started !!!
we are here in dashboard
{ id: '23' }
TypeError: dashboardfunc.productlist is not a function
Question is why it is so hard to get the results back , and why it needs to be so complicated to call a function , get the return data. Along with that whats the deal with callback v/s promise ( yeah I read almost all post in it still my naive brain cant process it)
Try these small fixes for the start:
admindashboard.js exports the only function, but app.js tries to use it as a property of an object. You need either this type of export:
module.exports = { productlist };
or this using:
dashboardfunc().then
The argument in the imported function call is missing. Try dashboardfunc(data).then instead of mentioned dashboardfunc.productlist().then.
resolve callback is not used in productlist() function. Use it to return the data from the promise: resolve(results); instead of return results;.
Be consistent in error handling. Use:
if (err) {
reject(err)
}
else {
if (results === undefined) {
reject(new Error("Error rows is undefined"));
}
instead of:
if (err) {
console.log(err)
}
else {
if (results === undefined) {
reject(new Error("Error rows is undefined"));
}

NodeJS: understanding promise

I am starting to use promise in NodeJS. The requirement is to use these because of async calls. Here is the first code I wrote for promise.
function asyncFunc(data) {
return new Promise(
function(resolve, reject) {
try {
resolve(data);
} catch (err) {
reject("Custom Error");
}
});
}
//Usage:
asyncFunc('Sample String')
.then(result => { console.log(result); })
.catch(error => { console.log(error); });
//Output:
Sample String
null
//If I change the code to:
function asyncFunc(data) {
return new Promise(
function(resolve, reject) {
try {
reject("Custom Error");
} catch (err) {
resolve("Data");
}
});
}
//Output:
//Exception has occurred: string
//I get the above exception at line: reject("Custom Error");
So the question is "reject" can only be used from "catch" block? Why can't I raise "reject" event manually? What is the scenario "reject" is used? Can someone provide me a better example where I can use both "resolve" and "reject"?
You can use reject if you want, of course.
Let's suppose you have a function that resolves a promise if a person is adult, and rejects it if not.
You'd have something like this:
function asyncFunc(age) {
return new Promise((resolve, reject) => {
if(age >= 18) {
resolve(true);
} else {
// here you call reject manually outside of a catch block
reject(false);
// or
// reject(Error('not adult'));
}
});
}
usage:
asyncFunc(19).then(result => {
console.log(result); // true
})
.catch(error => {
console.log(error); // false or Error('not adult')
});
Probably you got something like (node:5009) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Looks like you run your asyncFunc(..) in console. In this case node.js first execute your function after your hit Enter. Try to take your code to curly brackets like this:
{
asyncFunc('Sample String')
.then(result => { console.log(result); })
.catch(error => { console.log(error); });
}
In case of a try/catch block you usually reject at catch but you can also reject in try.
resolve and reject are basically callbacks for Promise. if you resolve it will got to the next chain if you reject it will break the chain.
So should use reject when an error occurs cause reject will break the promise chain.
For example.
Lets say you have a function that works with callback and you want to wrap it in a Promise like function. This function will check if user exists in database. If the User is found it will return true if not false and if there is an error in database (eg connection) it will reject.
function checkUserExist(id) {
return new Promise((resolve, reject) => {
checkUserExistInDatabase(id, function(result, error) {
if (error) {
reject(error);
}
if (result != null) {
resolve(true);
} else {
resolve(false);
}
})
});
}
function databaseError() {
return new Promise((resolve, reject) => {
reject();
})
}
var idsThatExist = [];
checkUserExist(1).then(function(exist) {
if (exist)
idsThatExist.push(1);
return checkUserExist(2)
}).then(function(exist) {
if (exist)
idsThatExist.push(2);
return databaseError(3)
}).then(function(exist) {
//WILL never Reach here
if (exist)
idsThatExist.push(3);
return checkUserExist(4)
}).then(function(exist) {
if (exist)
idsThatExist.push(4);
}).catch(function(err) {
//it will skip checkUserExist(4)
console.log('I got rejected after checked users:'
idsThatExist)
})
So the question is "reject" can only be used from "catch" block?
No, You can use reject anywhere. Catch isn't necessary to use reject
Why can't I raise "reject" event manually?
You can reject using creating new Promise() or static methods of Promise . See promiseUsingNew() and promiseUsingStaticMethod()
What is the scenario "reject" is used?
try/catch is used for error handling in synchronous programming. resolve & reject is for error handling in asynchronous programming operation instead of callbacks.
Can someone provide me a better example where I can use both "resolve" and "reject"?
'use strict';
function promiseUsingNew(marks) {
return new Promise((resolve, reject) => {
if (marks < 0 || marks > 100) {
return reject('Invalid marks');
}
if (marks >= 40) {
return resolve('You passed');
} else {
return resolve('You Failed');
}
});
}
function promiseUsingStaticMethod(marks) {
if (marks < 0 || marks > 100) {
return Promise.reject('Invalid marks');
}
if (marks >= 40) {
return Promise.resolve('You passed');
} else {
return Promise.resolve('You Failed');
}
}
// you can use promiseUsingNew(marks) or promiseUsingStaticMethod(marks)
promiseUsingNew(221).then((result) => {
console.log(result);
}).catch((error) => {
console.log(error);
});

Resources