promise reject not working with mysql error - javascript

I am trying to get return an mysql data using promises and it works, but when I try to create an error in mysql on purpose but then I am getting this error .
(node:28464) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Users not found
(node:28464) 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 checked everywhere and it says to use .catch but its odd that I am using catch but cannot figure out the problem. Normally I would like to know how to solve this instead of just continuing without knowing the right way.
This is the model..
getAllUser =
new Promise((resolve, reject) => {
db.query('SELECT * from users', function (error, results, fields) {
if (error){
return reject('Users not found');
}else{
resolve(results[0]);
}
});
});
module.exports = {
getAllUser
};
And here is how I am calling the model, the model in the top should return an error since the mysql table is called user not users.
router.get('/db',(req,res,next)=>{
getAllUser.then((result)=>{
console.log(result);
}).catch((e) => {
console.log(e);
});
});

You have error in your model file. Function which return promise should be created instead Promise.
Working code:
Model:
getAllUser = () => new Promise((resolve, reject) => {
db.query('SELECT * from users', function (error, results, fields) {
if (error){
return reject('Users not found');
}else{
resolve(results[0]);
}
});
});
module.exports = {
getAllUser
};
Router:
router.get('/db',(req,res,next)=>{
getAllUser.then((result)=>{
console.log(result);
}).catch((e) => {
console.log(e);
});
});

Related

NodeJS UnhandledPromise warning when connecting to MongoDB

I am trying to connect to my MongoDB instance using nodejs. I expose the endpoint /mongo which is supposed to trigger the connection and creation of a document in the mongo db, as follows:
app.get('/mongo', (req, res) => {
try{
invoke();
} catch(err){
console.log(err);
}
res.send('all good.');
});
async function invoke() {
client.connect(err => {
const collection = client.db("CodigoInitiative").collection("Registered");
//create document to be inserted
const pizzaDocument = {
name: "Pizza",
shape: "round",
toppings: [ "Pepperoni", "mozzarella" ],
};
// perform actions on the collection object
const result = collection.insertOne(pizzaDocument);
console.log(result.insertedCount);
//close the database connection
client.close();
});
}
When I hit the endpoint though, it returns with the following error:
(node:15052) UnhandledPromiseRejectionWarning: MongoError: topology was destroyed. 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)
I'm confused because the method invocation was wrapped around a try/catch block, even though the error log claims it wasn't. Where did I go wrong here?
There could be connection error in your environment. And the error was a rejected promise, you cannot catch it via the try / catch block because the error was generated on asynchronous call stack.
an async function should alway return a promise:
async function invoke () {
return new Promise((resolve, reject) => {
client.connect(err => {
if (err) return reject(err)
...
})
})
}
the returned promise should be handled with .catch:
app.get('/mongo', (req, res) => {
invoke().then(() => res.send('all good'))
.catch(err => console.log('invoke error:', err))
})

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);
}
}
}
})
);

Global connection already exists despite sql.close()

I created query function to connect to mssql database like below:
query(query) {
return sql.connect(config.connection.sqlserver).then(() => sql.query(query)).then((result) => {
sql.close();
return result.recordset;
}).catch((err) => console.log(err));
},
When I'm starting nodejs server everything works fine. When I'm doing refresh many times I'm getting result from database e.g.
But when I'm sending request from client side to server side I'm getting an error like below:
(node:19724) UnhandledPromiseRejectionWarning: Error: Global connection already
exists. Call sql.close() first.
at Object.connect (C:\repos\mtg-app\node_modules\mssql\lib\base.js:1723:31)
at query (C:\repos\mtg-app\server\query.js:6:16)
at asyncCall (C:\repos\mtg-app\server\routes\index.js:19:11)
at router.get (C:\repos\mtg-app\server\routes\index.js:29:3)
at Layer.handle [as handle_request] (C:\repos\mtg-app\node_modules\express\l
ib\router\layer.js:95:5)
at next (C:\repos\mtg-app\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\repos\mtg-app\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (C:\repos\mtg-app\node_modules\express\lib\router\layer.js:95:5)
at C:\repos\mtg-app\node_modules\express\lib\router\index.js:281:22
at Function.process_params (C:\repos\mtg-app\node_modules\express\lib\router\index.js:335:12)
(node:19724) 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:19724) [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 don't understand first of all why it's working only on server and secondly why it's not working despite sql.close() method?
Please explain me this issue very well.
In regards to my comment, something along these lines.
async function query(q) {
return new Promise((resolve, reject) => {
new sql.ConnectionPool({/* Config */}).connect().then((pool) => {
return pool.request().query(q)
}).then((result) => {
// Resolve result
resolve(result);
// Close sql.close();
sql.close();
}).catch((error) => {
// Reject error
reject(error);
// Close sql.close();
sql.close();
});
});
}
query(`SELECT * FROM`)
.then((response) => {
// Success
console.log(response);
})
.catch((error) => {
// Error
console.log(error);
})
.finally(() => {
// Clean-up
});
Or another way, with mysqlijs all from the documentation here.
const mysql = require('mysql');
const pool = mysql.createPool({/* Config */});
pool.getConnection(function(error, connection) {
if (error) {
throw error;
}
// Use the connection
connection.query(`SELECT * FROM`, function (error, results, fields) {
// When done with the connection, release it.
connection.release();
// Handle error after the release.
if (error) throw error;
// Don't use the connection here, it has been returned to the pool.
});
});
pool.on('acquire', function (connection) {
console.log('Connection %d acquired', connection.threadId);
});
pool.on('enqueue', function () {
console.log('Waiting for available connection slot');
});
pool.on('release', function (connection) {
console.log('Connection %d released', connection.threadId);
});
pool.end(function (err) {
// Ending all connection the the MySQL pool.
});
I did it in the simpler way than below. But thanks Raymond because I realized that I should use ConnectionPool.
My query module:
/* eslint-disable import/no-unresolved */
const mssql = require('mssql');
const database = require('./config/connection');
const pool = new mssql.ConnectionPool(database.config).connect();
async function query(sql) {
try {
const connection = await pool;
const result = await connection.query(sql);
return result.recordset;
} catch (err) {
console.log('SQL error', err);
}
return [];
}
module.exports.query = query;
Now when I want to use it e.g. in router module:
router.get('/get-users', (req, res, next) => {
const usersStandings = [];
sql.query('select u.name, s.points from dbo.[user] u join dbo.standings s on s.id = u.standings_id join dbo.category c on c.id = s.category_id where c.type = \'Tournament\' order by points desc').then((rows) => {
rows.forEach((element) => {
usersStandings.push(element);
});
res.send(usersStandings);
});
});
Now I don't have problems with Global connection etc.

Async/await call returns undefined when used in conjunction with promises

I am having an issue where an Async call to my database returns undefined.
The function "findOne" retrieves one row from the database, but the .then(... function is executing before the row is returned.
I've tried changing what I return in the DB function findOne as well as adding an 'await' on the function call. I've also tried using Promise.resolve(db.findOne({requestbody}).then(... but no luck with that either.
Here is the db.findOne method
const findOne = async (req) => {
const { teamId, channelId, isClosed } = req;
return db.query('SELECT * FROM polls where team_id= $1 and channel_id =$2 and is_closed = $3 LIMIT 1',
[teamId, channelId, isClosed],
(error, results) => {
if (error) {
throw error;
}
console.log("\nDBRes: \n", results.rows[0])
return results.rows[0];
}
);
};
And here is where I call the function
app.post('/', (req, res) => {
const slashCommand = req.body.command;
switch (slashCommand) {
//...
//... Some other code
//...
case 'results':
db.findOne({
teamId: requestBody.team_id,
channelId: requestBody.channel_id,
isClosed: false,
})
.then((row) => {
console.log(row);
const poll = pollFuncs.getPollfromResultRow(row);
const displayText = pollFuncs.getFormattedPollResults(poll);
res.status(200).send({
text: displayText,
});
});
break;
//... The rest of the function
Here are the logs I am getting.
Note* I am currently logging the "row" object both inside the .then(...) function and inside the pollFuncs.getPollfromResultRow(row); function
Bot is listening on port 3000
undefined
undefined
(node:14000) UnhandledPromiseRejectionWarning: TypeError: Cannot destructure property `id` of 'undefined' or 'null'.
at Object.getPollfromResultRow (C:\Users\ztb0504\Documents\Projects\Node\werewolfmod\pollFunctions.js:97:125)
at db.findOne.then (C:\Users\ztb0504\Documents\Projects\Node\werewolfmod\index.js:59:56)
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:14000) 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:14000) [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.
DBRes:
{ id: '22',
poll_title: 'This is a new Pollstgresql',
//The rest of the expected data....
}
I'd appreciate any guidance on how to get this to return data as expected.
Thank you!
You're mixing plain callbacks and promises and it is causing you problems. It will be a lot easier if you don't do that.
If you pass a plain callback to db.query(), then it won't return a promise. In fact, it will return nothing (undefined). So, when you do return db.query(), all you're doing is returning undefined.
Change to this:
const findOne = async (req) => {
const { teamId, channelId, isClosed } = req;
return db.query('SELECT * FROM polls where team_id= $1 and channel_id =$2 and is_closed = $3 LIMIT 1',
[teamId, channelId, isClosed]).then(results) => {
console.log("\nDBRes: \n", results.rows[0])
return results.rows[0];
});
};
The, you also need error handling in your request handler if there are any errors in the query. Promise handling should nearly always have a .catch() somewhere to handle errors:
case 'results':
db.findOne({
teamId: requestBody.team_id,
channelId: requestBody.channel_id,
isClosed: false,
}).then((row) => {
console.log(row);
const poll = pollFuncs.getPollfromResultRow(row);
const displayText = pollFuncs.getFormattedPollResults(poll);
res.status(200).send({
text: displayText,
});
}).catch(err => {
console.log(err);
res.sendStatus(500);
});
break;

When start code in Promise in Node.js ES6?

I make a method that create a promise for each element in array.
queries.push(function (collection) {
new Promise((resolve, reject) => {
collection.find({}).limit(3).toArray(function (err, docs) {
if (err) reject(err);
resolve(docs);
});
});
});
const getAnalyticsPromises = (collection) => {
let promises = [];
queries.each((item) => {
promises.push(item(collection));
});
console.log(queries);
return promises;
}
This code return this errors:
(node:10464) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: queries.each is not a function
(node:10464) 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: When the promise is called? When i create it:
promises.push(item(collection));
or when i call it with then() function?
Well the error you have is about queries has not method each - you should use forEach instead.
Bescides you should return promise from your function:
queries.push(function (collection) {
return new Promise((resolve, reject) => {
collection.find({}).limit(3).toArray(function (err, docs) {
if (err) reject(err);
resolve(docs);
});
});
});
So when you call item(collection) where item is one of your anonymous functions, the promise would be created.
And now you can handle with it whatever you need, for example:
let p = item(collection);
p.then(...).catch(...)

Categories

Resources