UnhandledPromiseRejection in Express.js - javascript

I hope I'm supplying enough information for this question, but I can't understand why my callback function returns Unhandled Promise Rejection when I on purpose want to catch the error:
(node:3144) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Can't set headers after they are sent.
(node:3144) 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'm calling the function here in routes:
router.route("/home/create")
.post(Authorization, function(req, res) {
CreateSnippetResource(req, function(err) {
if (err) {
console.log(err.message)
}
res.redirect("/home")
});
});
And the "CreateSnippetResource"-function:
(function() {
let User = require("../../Models/User");
let Snippet = require("../../Models/Snippet");
/**
* Create a new snippet and save it to database
* #param request
* #param callback
*/
module.exports = function(request, callback) {
callback(
User.findOne({ user: request.session.Auth.username }, function(err, user) {
if (err || user === null) {
callback("User not found")
}
var snippet = new Snippet({
title: request.body.snippetName.split(".").shift(),
fileName: "." + request.body.snippetName.split(".").pop(),
postedBy: user._id,
snippet: [{
text: " "
}]
});
snippet.save().then().catch(function(err) {
callback(err)
});
}))
};
}());
I'm trying to handle the error when title is not entered. I have a validator in my schema-module that looks like this:
SnippetSchema.path("title").validate(function(title) {
return title.length > 0;
}, "The title is empty");
And indeed the returned error-message from the callback CreateSnippetResource is The title is empty. So how come I get this Promise-error?
I'm assuming it has something to do with how I handle the snippet.save(), but can't see how it's not handled. Can you please help?

Why does my callback function return Unhandled Promise Rejection when I on purpose want to catch the error?
That will happen when your callback throws another exception. This will reject the promise returned by the .catch(…) call, and that rejection is nowhere handled.

As it turns out, I was an idiot, and forgot that I accidentally putted the whole function in the callback. The callback is then executed twice, and thus returns Error: Can't set headers after they are sent.

Related

Unhandled promise rejection nodejs

I am trying to use openweather-apis to connect to a dialogflow agent. I am new to promises and I keep getting the warning UnhandledPromiseRejectionWarning and I'm not sure on how to fix this.
Currently I have 2 files weather.js, which makes the api call
const api = require("openweather-apis")
api.setAPPID(process.env.API_KEY)
api.setUnits("metric")
module.exports = {
setCity: function(city) {
api.setCity(city)
},
getWeather: function() {
return new Promise(function(resolve, reject) {
api.getTemperature(function(err, temp) {
if (err) reject(err)
resolve(temp)
})
})
}
}
And I make use of weatherinCity.js, which retrieves the city from the agent, calls the calling function and then sends a response to the user.
const weather = require("../../weather")
module.exports = {
fulfillment: function(agent) {
const city = agent.parameters.geo_city
weather.setCity(city)
weather.getWeather().then(function(temp) {
agent.add(
"It is ${temp} degrees Celcius in ${city}"
)
}).catch(() => {
console.error("Something went wrong")
})
}
}
full error message:
(node:2896) UnhandledPromiseRejectionWarning: Error: No responses defined for platform: DIALOGFLOW_CONSOLE
at V2Agent.sendResponses_ (C:\Users\Coen\Desktop\ciphix-ca-case\node_modules\dialogflow-fulfillment\src\v2-agent.js:243:13)
at WebhookClient.send_ (C:\Users\Coen\Desktop\ciphix-ca-case\node_modules\dialogflow-fulfillment\src\dialogflow-fulfillment.js:505:17)
at C:\Users\Coen\Desktop\ciphix-ca-case\node_modules\dialogflow-fulfillment\src\dialogflow-fulfillment.js:316:38
at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:2896) 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(). To terminate the node process on unhandled
promise rejection, use the CLI flag `--unhandled-rejections=strict` (see
https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode).
(rejection id: 1)
(node:2896) [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.
This error indeed happened because this code fails to handle the Promise Rejection. While I'm not sure which Promise Rejection that failed to handle, but based on this and this GitHub discussions. It seems you need to return the agent.add() function.
I recommend trying async-await style with the consequence that you have to add a try catch block
module.exports = {
fulfillment: async function(agent) {
try {
const city = agent.parameters.geo_city
weather.setCity(city)
let temp = await weather.getWeather()
agent.add(
"It is ${temp} degrees Celcius in ${city}"
)
} catch (err) {
console.error("Something went wrong")
console.error(err)
}
}
}
Every error that is thrown on the try block should be caught in a catch block. Don't forget to add async before the function.
it will not solve your problem but generally speaking, i would add "return" after if(err). because otherwise the call to resolve would be done. in your particular case it will do no harm, as because of the nature of promises it will be ignored. but if you had written anything between reject and resolve it would have been executed.
// best practice
if (err) return reject(err)
for your problem, i've just tried this fast test to convice myself that even throws are catched by .catch() so i think you must be running a bad/old nodejs version, or the code you provided is not complete, and the failure is elsewere. I dont see any line pointing to your own code in the log O_o (only node_modules).
which nodejs version is it ?
var p = new Promise((resolve, reject) => {
throw new Error('test');
resolve('ok')
})
p.then(console.log).catch(function(err) {
console.error('err', err)
});

How to solve UnhandledPromiseRejectionWarning in NodeJS testing framework

I'm using custom commands in my testing framework based on Nightwatch.js. I want to do a PUT request via superagent. This os my custom command:
const superagent = require("superagent");
exports.command = function(url, header, body, callback) {
return superagent
.put(url)
.send(body) // sends a JSON post body
.set(header)
.then(result => {
callback(true, result);
return this;
})
.catch(err => {
if (err) {
callback(false, err);
return this;
}
});
};
And this command I'm using in my tests:
return client
.apiPut(apiUrl, header, body, function(status, result) {
assert.isTrue(status, "response status is false");
assert.isTrue(result.ok, "response result is NOT ok");
})
If everything is fine with the PUT request (status == true and successful response) then everything is fine and the test will finish, but if the PUT request is not successful (status != true and an error as result) I'm getting the following error message and the current Node process does not finish:
09:11:12 (node:103) UnhandledPromiseRejectionWarning: AssertionError: response status is false: expected false to be true
09:11:12 at /var/jenkins_home/jobs/MYJOB/workspace/testautomation/end2end-web-tests/pageobjects/MyPageView.js:59:20
09:11:12 at superagent.put.send.set.then.catch.err (/var/jenkins_home/jobs/MYJOB/workspace/testautomation/end2end-web-tests/commands/apiPut.js:14:9)
09:11:12 at <anonymous>
09:11:12 at process._tickCallback (internal/process/next_tick.js:189:7)
09:11:12 (node:103) 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)
09:11:12 (node:103) [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.
But I don't know what I'm doing wrong with the callback in my custom command. What should I do to solve that issue?
Thanks for the help. Now it is running. I've replaced the promise and replaced it completely with callbacks. Now it is working :)
const superagent = require("superagent");
exports.command = function(url, header, body, callback) {
return superagent
.put(url)
.send(body) // sends a JSON post body
.set(header)
.end((error, result) => {
if (error) {
callback(false, result, error);
} else {
callback(true, result, error);
}
});
};

How do I handle the UnhandledPromiseRejectionWarning in Node.JS

I have a few methods that use the request module to get images from URLs and returns it as a Promise, it works but when the image isn't found it rejects the promise with the status code 404. I looked into that warning and it is said that to handle the rejection you have to setup a catch callback after then() but I don't use then(), I use async/await.
This is the code to get the picture:
/**
* Returns picture from S3
* #param {String} filename Name of the file with extension
* #returns {String} Base64 string of the file
*/
getPictureFromS3: function (filename) {
return new Promise((resolve, reject) => {
let url = this.getURLFromS3(filename);
request(url, (err, res, body) => {
if (err) reject(err);
if (res.statusCode !== 200) {
reject(`Invalid status code <${res.statusCode}>`);
}
resolve(new Buffer.from(body).toString('base64'));
});
});
}
And this is how I call the method:
try{
socket.on('server get pictures', () => db.getPictures(data=>{
if(data!==null){
data.forEach(async e=>{
let picture = await utils.getPictureFromS3(e.getFilename());
});
}
}));
}catch(err){
console.log(err);
}
Full warning:
(node:256) UnhandledPromiseRejectionWarning: Invalid status code <404>
(node:256) 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:256) [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.
Using Node v10.14.2.
There are two problems here
You care trying to do async operation inside forEach which doesn't work with promises. You need to use for..of loop or Promise.all if you can do things in parallel.
The exception is raise inside the listener so it will not bubble up outside so your catch wouldn't be executed. You need to move your try catch inside. Something like this
socket.on("server get pictures", () =>
db.getPictures(data => {
if (data !== null) {
for(const e of data) {
try {
let picture = await utils.getPictureFromS3(e.getFilename());
} catch (err) {
console.log(err);
}
}
}
})
);

Module Promise: UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'collection' of undefined

i just searched for my problems around in the stackoverflow's discussions but nothings similar with my issued. So, in this case, i just want to update my collection and then use the 'Promise' module instead use the callbacks / anonymous functions as normally i did. but the error comes up when I execute the js's application in cmd.
Here my simple code:
var Promise = require('promise'); // use the 'promise' module
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost/EmployeeDB';
MongoClient.connect(url)
.then(function(err, db) {
db.collection('Employee').updateOne({
"EmployeeName": "Jeffrey"
}, {
$set: {
"EmployeeName": "Jeffrey Scurgs"
}
});
});
and the error results when i executed the code in cmd:
(node:8600) UnhandledPromiseRejectionWarning: TypeError: Cannot read
property 'collection' of undefined
at C:\Users\DELL\guru99\5_Promise\app_promise.js:7:9
at
at process._tickCallback (internal/process/next_tick.js:189:7) (node:8600) 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:8600) [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.
so, is there any wrong code in my code above?
thanks for helping...
sorry for my bad english
Your approach is correct but you a missed one thing.
When you don't provide callback parameters mongo ORM return a promise. Here is the corrected code:
MongoClient.connect(url)
.then(function(db) { // <- db is first argument
db.collection('Employee').updateOne({
"EmployeeName": "Jeffrey"
}, {
$set: {
"EmployeeName": "Jeffrey Scurgs"
}
});
})
.catch(function (err) {})
The db variable can only be undefined if there was an error connecting to the database.
You need to check and fix any error shown. You can also share the error
var Promise = require('promise'); // use the 'promise' module
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost/EmployeeDB';
MongoClient.connect(url)
.then(function(err, db) {
if (err) {
return throw err; // Check the error
}
db.collection('Employee').updateOne({
"EmployeeName": "Jeffrey"
}, {
$set: {
"EmployeeName": "Jeffrey Scurgs"
}
});
});

Error "Unhandled promise rejection" with mysql query

I am trying to make a new data entry in BD with mysql from a page. But when throw me an error about promises
var mysql = require('mysql'); //Llamadi a MySql
var valida= require('./modulos/validaciones');
var conection = mysql.createConnection({
host: 'localhost', //Host
user: 'eleazarsb', //Usuario
password: 'eleazar616', //Contraseña
database: 'mydb' //Base de datos
}).connect(function(error) {
if (error) console.log('Problemas de conexion con mysql');
console.log("conexion Exitosa!");
});
var validaciones = {
user: false,
mail: false,
ced: false
}
//Pendiente: 02
valida.user(data).then((rows) => {
validaciones.user = rows;
})
valida.mail(data).then((rows) => {
validaciones.mail = rows;
})
valida.ced(data).then((rows) => {
validaciones.ced = rows;
registrar(validaciones);
})
function registrar(validaciones) {
if (validaciones.user == false && validaciones.mail == false && validaciones.ced == false) {
var query = conection.query(data.sqlquery(), (error, columna, campos) => {
if (error) throw error;
console.log("Entra en registro de BD");
console.log(columna);
});
}
else {
console.log("No se registro nada");
};
return query;
};
When 'conection.query(data.sqlquery()...' is execute the console throw me this error
(node:1588) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Cannot read property 'query' of undefined
(node:1588) [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.
So, i cant see where is the error if conection.query( is declared in the beginning with conection=mysql.createConnection
I am new programming with NodeJs so i i accept any comment or suggestion of good programming practices
valida return a promise declared in another file
exports.mail= (data)=>{
return new Promise ((resolve,reject)=>{
var query=conection.query(data.valida_mail(),(error,rows)=>{
if (error) return reject (error);
if(rows[0]){
console.log("Email Invalido!");
resolve(true);
} else {
console.log("Email Valido");
resolve(false);
}
});
})
};
... for example
Will's explained why your code is failing. The reason you're seeing it as an "Unhandled rejection" error is that you're not handling your promises correctly.
One of the rules of promises is that you either pass on the promise chain to the level above you, or you handle errors. This code does neither (nor do others written largely the same way):
valida.user(data).then((rows) => {
validaciones.user = rows;
})
What if the promise returned by valida.user(data) rejects? Answer: Nothing handles it.
You must either hand off the promise then creates to something else, or handle rejections. (If you hand it off, the thing you had it off to has to hand it off again, or handle errors.)
To make that code handle errors, add a catch handler:
valida.user(data).then((rows) => {
validaciones.user = rows;
}).catch(err => {
// Do something with the error here
});
The error message is a bit misleading here. The important part is TypeError: Cannot read property 'query' of undefined which is referring to conection being undefined when it is called in registrar when that is called in the promise handler attached to valida.ced.
The issue is with the code:
var conection = mysql.createConnection({
...
}).connect(function(error) {
...
});
which is assigning the return value of the call to Connection.connect to your conection variable. Connection.connection does not return a value (source), so later when that promise resolves and tries to execute registrar(), conection is still and forever undefined, so there's no such thing as conection.query to be called. Try:
var conection = mysql.createConnection({
...
});
conection.connect(function(error) {
...
});
As T.J. points out, the other important part of the error message is that you should provide code to handle rejected promises. Use the catch function to attach these handlers.
Adding to the answers .
You are using node.js promises . So to handle all type of 'Unhandled promise rejection'. use this code at the main node.js app file
process.on('unhandledRejection', error => {
// Will print "unhandledRejection err is not defined"
console.log('unhandledRejection', error);
});
In case you missed catching some promise this will handle all of them.
Process
Node.js process is global , it contains unhandledRejection event for handling unhandled promise rejection .

Categories

Resources