(node:14224) UnhandledPromiseRejectionWarning - javascript

I am using below for JWT:
let jwtoptions = {};
jwtoptions.jwtFromRequest = ExtractJWT.fromAuthHeaderAsBearerToken();
jwtoptions.secretOrKey = DB.secret;
let Strategy = new JWTStrategy(jwtoptions,(jwt_payload,done)=>{
User.findById(jwt_payload.id)
.then(User =>{
return done(null, User);
})
.catch(err =>{
return done(err,false);
})
})
passport.use(Strategy);
But its showing me below error:
(node:14224) UnhandledPromiseRejectionWarning: TypeError: done is not a function
(node:13568) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch().

Haven't used passport-jwt but from reading the docs it seems you need to use a callback instead of a promise
let Strategy = new JWTStrategy(jwtoptions,(jwt_payload,done)=>{
User.findById(jwt_payload.id, (err, user) => {
if (err) return done(err, false);
return done(null, user);
});
});

Related

nodejs promises giving Unhandled Promise Rejection which seems to be handled properly

The problem is that i am getting UNhandledPromiseRejection error eveen though i think i have handled all the cases. The code flows from profileRoutes to Controller to Utils where the error comes first.
Inside the profileRoutes.js
router.get('/:username', async (r, s) => {
try{
let profileData = await getProfileData(r.params.username);
s.json({ success: true, payload: profileData });
}catch(err){
console.log('ending request processing by responding a error');
s.status(500).json({ success: false, message: 'err[0].message' });
}
});
Inside the controllers/index.js
const fetchQueue = [getUserRepos];
async function getProfileData(username) {
let profileData = {};
try{
let results = await Promise.all(fetchQueue.map(item => item(username)));
for (let i = 0; i < results.length; i++) {
profileData[getKeys[i]] = results[i];
}
return profileData;
}catch(err){
console.log('error log in controller/index getProfileData function');
throw err;
}
}
const getUserRepos = async (username) => {
try {
// const res = await utils.gqlSender(username, 'userRepos', { createdAt });
const res = await utils.gqlSender(username, 'userReposData');
return res.user.repositories;
} catch (err) {
console.log('error log in controller/index getUserRepos function');
throw err;
}
};
Inside the utils/index.js
const gqlSender = async (username, type, opt = {}) => {
axios.post('', {
query: gqlQuery(username, type, opt) // generates a needed graphQL query
}).then(res => {
if(res.data.errors) { // this is where the error is recieved and so i reject promise.
console.log('bef###re');
return Promise.reject (res.data.errors);
}
console.log('###',res.data);
return res.data;
}).catch(err => {
console.log('error in making axios request inside utils/index gqlSender function');
throw err;
// return Promise.reject(err);
});
The stack trace on making get request to /:username is-
error log in controller/index getUserRepos function
error log in controller/index getProfileData function
ending request processing by responding a error
bef###re
error in making axios request inside utils/index gqlSender function
(node:11260) UnhandledPromiseRejectionWarning: [object Array]
(node:11260) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:11260) [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.
I dont think i am missing any Promise Rejection.
Any help is appreciated. Thanks.
i have referred these answers previously -
What's the difference between returning value or Promise.resolve from then()
Do I need to return after early resolve/reject?
Your gqlSender function is not returning the promise that will get rejected, so it is not handled anywhere. You should write either
const gqlSender = (username, type, opt = {}) => {
return axios.post('', {
// ^^^^^^
query: gqlQuery(username, type, opt) // generates a needed graphQL query
}).then(res => {
if (res.data.errors) {
console.log('error in making axios request inside utils/index gqlSender function');
throw res.data.errors;
} else {
console.log('###',res.data);
return res.data;
}
});
};
or
const gqlSender = async (username, type, opt = {}) => {
// ^^^^^
const res = await axios.post('', {
query: gqlQuery(username, type, opt) // generates a needed graphQL query
});
if (res.data.errors) {
console.log('error in making axios request inside utils/index gqlSender function');
throw res.data.errors;
} else {
console.log('###',res.data);
return res.data;
}
}

How to catch the exception in the right way? [beginner]

There is the following function, which doesn't catch MyException.
const myFunction = () => async (req, res, next) => {
try {
myHTTPRequest().then(async (response) => {
if (response.data.results.length != 1) {
throw new MyException('MyError');
}
res.end('All good');
})
.catch((error) => {
throw error; //Doesn't work
});
} catch (error) {
console.log('This block should catch MyException, but it doesn't');
next(error);
}
};
Instead, the application writes following error message into the console
(node:45746) UnhandledPromiseRejectionWarning
(node:45746) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:45746) [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.
The question is, how does the code need to be adjusted to catch MyException in the expected Catch-Block?
The issue is that you're mixing .then/.catch with try/catch.
If you want the code to enter the try/catch in an async function, you have to use the await keyword on the Promise.
You can drop the .catch since it's doing nothing, you're throwing again the error, and that's causing the UnhandledPromiseRejectionWarning
const myFunction = () => (req, res, next) => {
try {
const response = await myHTTPRequest();
if (response.data.results.length != 1) {
throw new MyException('MyError');
}
res.end('All good');
} catch (error) {
next(error);
}
};
Using .then/catch without async/await the code would be:
const myFunction = () => (req, res, next) => {
myHTTPRequest().then((response) => {
if (response.data.results.length != 1) {
throw new MyException('MyError');
}
res.end('All good');
})
.catch((error) => {
throw error;
// It makes no sense to throw again in here
// But I'm showing you how to handle it if you do
})
.catch(error => {
next(error);
})
};
Of course the double .catch doesn't make sense, and you should remove it, leaving a single one:
const myFunction = () => (req, res, next) => {
myHTTPRequest().then((response) => {
if (response.data.results.length != 1) {
throw new MyException('MyError');
}
res.end('All good');
})
.catch(error => {
next(error);
})
};

How to add a catch statement to fix Unhandled promise rejection warning

I am trying to add user authentication to my site. The register route on my page works perfectly but I receive an Unhandled promise rejection warning when I try to send a request to the login route.
I've tried adding .catch(err => console.log(err)); and
.catch(console.log("Something's gone wrong.")); to the end of both .findOne().then() and .compare().then(), but that didn't help.
router.post("/login", (req, res) => {
const email = req.body.email;
const password = req.body.passowrd;
User.findOne({ email }).then(user => {
if (!user) {
return res.status(404).json({ email: "User not found" });
}
bcrypt.compare(password, user.passowrd).then(isMatch => {
if (isMatch) {
res.json({ msg: "Success" });
} else {
return res.status(400).json({ password: "Password incorrect" });
}
});
});
});
The code is supposed to simply send back a message that the passwords match, so I can later generate a token. I get this error:
(node:18152) UnhandledPromiseRejectionWarning: Error: Illegal arguments: undefined, undefined
at _async (/home/jok/code/node_modules/bcryptjs/dist/bcrypt.js:286:46)
at /home/jok/code/node_modules/bcryptjs/dist/bcrypt.js:307:17
at new Promise (<anonymous>)
at Object.bcrypt.compare (/home/jok/code/node_modules/bcryptjs/dist/bcrypt.js:306:20)
at User.findOne.then.user (/home/jok/code/routes/api/users.js:64:12)
at processTicksAndRejections (internal/process/next_tick.js:81:5)
(node:18152) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:18152) [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.
The UnhandledPromiseRejectionWarning occurs because you're not handling the Promise rejection, meaning that you're missing a .catch handler.
bcrypt.compare(password, user.passowrd).then(isMatch => {
if (isMatch) {
res.json({ msg: "Success" });
} else {
return res.status(400).json({ password: "Password incorrect" });
}
})
.catch(err => {
res.status(500).send('Internal server error');
});
In this particular case, it seems that password & user.passowrd are undefined. The latter probable because of a typo: passowrd => password.
So it's recommended to check that the arguments sent to your route are valid.
router.post("/login", (req, res) => {
const email = req.body.email;
const password = req.body.passowrd;
if(!email || !password)
return res.status(400).send('email & password are required');
/* ... */
});
Since you're missing the .catch handler also on the .findOne Promise, it's always better to chain Promises instead of nesting them as you're doing. So here's the complete code:
router.post("/login", (req, res) => {
const email = req.body.email;
const password = req.body.passowrd;
if (!email || !password)
return res.status(400).send('email & password are required');
User.findOne({ email })
.then(user => {
if (!user) {
return res.status(404)
.json({ message: "User not found" });
}
return bcrypt.compare(password, user.passowrd);
})
.then(isMatch => {
if (typeof isMatch !== 'boolean')
return; // result from `res.status(404)...`
if (isMatch)
return res.json({ message: "Success" });
return res.status(400)
.json({ message: "Password incorrect" });
})
.catch(err => {
res.status(500).json({ message: 'Internal server error' });
});
});
I've tried adding .catch(err => console.log(err)); and
.catch(console.log("Something's gone wrong.")); to the end of both
.findOne().then() and .compare().then(), but that didn't help.
Either you didn't attach the handler correctly, or the warning was triggered in another code. But since the provided code does not have the .catch you mention, I can't confirm. Anyways, the above snippet won't trigger an UnhandledPromiseRejectionWarning
bcrypt.compare(myPlaintextPassword, hash, function(err, res) {
if (err) {
console.log(err);
}
// Use your response
});
That is not necessary to use promises in simple logic.

Call a function inside async function at a js class

Hi I'm new at javascript programming.
I have a node express project, I'm trying to create a login method inside my AuthenticationController class.
My login method is like this right now:
const User = require('../models/User')
class AuthenticationController {
async login(req, res) {
const { email, password } = req.body
console.log('step 1')
var hashPassword = await userPassword(email)
console.log(hashPassword)
console.log('step 2')
return res.status(200).json({ 'msg': 'Log in OK!' })
}
userPassword(email) {
User.findOne({ email: email }).exec(function(err, user) {
if (err) return err
else return user.password
})
}
}
But I got an error saying that userPassword is undefined, I couldn't figure out why. So my doubts are: why this is happening, and how to do it correctly ?
I also checked out this questions, but they didn't helped me:
How to call an async function
Async function inseide a class
The error message at my console:
(node:28968) UnhandledPromiseRejectionWarning: ReferenceError: userPassword is not defined
...
(node:28968) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:28968) [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.
login doesn't refer to userPassword method but to the function of the same name which doesn't exist.
Promises are supposed to be be chained and they aren't. userPassword is expected to return a promise but it uses obsolete Mongoose callback API.
That UnhandledPromiseRejectionWarning is shown means that errors weren't correctly handled in login while they should. As explained in this answer, Express don't support promises so errors should be handled by a developer.
It should be:
async login(req, res) {
try {
const { email, password } = req.body
var hashPassword = await this.userPassword(email)
return res.status(200).json({ 'msg': 'Log in OK!' })
} catch (err) {
// handle error
}
}
async userPassword(email) {
const { password } = await User.findOne({ email: email });
return password;
}
this error is coming because you are not handling error for the promise. Always use async/await inside try/catch block.
try{
async login(req, res) {
const { email, password } = req.body
console.log('step 1')
var hashPassword = await userPassword(email)
console.log(hashPassword)
console.log('step 2')
return res.status(200).json({ 'msg': 'Log in OK!' })
}
}catch(e){
console.log(e)
}

I cant handle promise rejections

I have a service that analyses websites, compresses their sources like CSS Documents, Images etc. I have 2 functions, one is Socket.IO socket.on() method with async callback function. Another is main function for service.
socket.on('run', async options => {
debug(`${options.target} Adresine Bir Kullanıcı İstek Yaptı!`);
let user = null;
console.log(options);
if(options.token) {
user = await User.findById(jwt.verify(options.token, config.get('jwtPrivateKey'))._id);
options.userId = user._id.toString();
} else if(options.visitor) {
user = await Visitor.findById(options.visitor._id);
if(user.report) {
return socket.emit('error', new Error('You have exceeded your report limit'));
} else {
options.userId = user._id.toString();
}
}
if(options.userId) {
let userType = await UserType.find({ name: user.type });
if(userType.length > 0 && ((user.type == 'Visitor' && user.report == undefined) || (user.reports.length < userType[0].rights.reportsLimit.limit || userType[0].rights.reportsLimit.unlimited))) {
options.rights = userType[0].rights;
let { error, data } = await wrapper(runService(options.target, options, socket));
if(error) {
console.log('Here', error);
return socket.emit('error', error);
}
.
.
.
}
.
.
.
}
});
In the above function,
let { error, data } = await wrapper(runService(options.target, options, socket));
if(error) {
console.log('Here', error);
return socket.emit('error', error);
}
This part is important, because I call my main async service function runService with my async function wrapper function that is named wrapper. The wrapper function is this;
const wrapper = promise => (
promise
.then(data => ({ data, error: null }))
.catch(error => ({ error, data: null }))
);
In my main async service function, I only throw an error;
async function runService(target, options, socket) {
throw new Error('any error');
}
But the expected output is much different from actual output. Here is the output of this code;
Here Error: any error
at startService (C:\Projeler\OpDetect\Background-Service\lib\app.js:404:11)
at Socket.socket.on (C:\Projeler\OpDetect\Background-Service\app.js:73:57)
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:16600) UnhandledPromiseRejectionWarning: Error: any error
at startService (C:\Projeler\OpDetect\Background-Service\lib\app.js:404:11)
at Socket.socket.on (C:\Projeler\OpDetect\Background-Service\app.js:73:57)
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:16600) UnhandledPromiseRejectionWarning: Unhandled promise rejection.
This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:16600) [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.
My expectation about the output is, like this;
Here Error: any error
at startService (C:\Projeler\OpDetect\Background-Service\lib\app.js:404:11)
at Socket.socket.on (C:\Projeler\OpDetect\Background-Service\app.js:73:57)
at process._tickCallback (internal/process/next_tick.js:68:7)
Because I already handled the promise rejection with my wrapper function and catched the rejection, Why is 2 more UnhandledPromiseRejectionWarning errors on rejection?
Also, the line,
return socket.emit('error', error);
is not calling for no reason. It should have been called when the if statement truthy. Why is not this socket.emit function called?
As best practice use try {} catch(){} with async/await.
For ex.
userUtils.signUp = async (userName) => {
try {
const callFunction = await userUtils.checkExistancy(userName);
if (!callFunction.isExist) {
...
} else {
...
}
} catch (err) {
console.log(err);
throw err;
}
};
in your case it will be like
socket.on('run', async options => {
try {
user = await User.findById(jwt.verify(options.token, config.get('jwtPrivateKey'))._id);
options.userId = user._id.toString();
return true;
} catch (err) {
throw err;
}});

Categories

Resources