try/catch block can't stop ER_DUP_ENTRY error from crashing my appliction - mysql

Im adding a duplicate to a mysql table and I want to handle elicited ER_DUP_ENTRY error comming back with a Try/Catch block but its just crashing anyway , is there any possible way to handle error and stop application from crashing using a try/catch block?
async function init() {
try {
connection.query(
'SOME INSERT QUERY',
(err, result, feilds) => {
if (err) throw err
console.log(result);
}
);
} catch (e) {
console.log(e);
}
}
init();

The node mysql-library does not support promises out of the box, which means query does not return a promise which you can await. So you can either wrap the query function in a promise yourself:
async function init() {
try {
const duplicateResult = await new Promise((resolve, reject) => {
connection.query(
'SOME INSERT QUERY',
(err, result, fields) => {
if (err) {
return reject(err);
}
resolve(result);
});
});
} catch (e) {
console.log(e);
}
}
or use util.promisify as Always Learning posted alternatively.

The problem is that connection.query returns undefined right away. Your catch is not involved because the call ends before the work is done and will call your callback function later. An exception that occurs during your callback is too late. You try/catch block has already completed.
You can use promisify to wait on it like this though:
const util = require("util");
function init() {
const queryPromise = util.promisify(connection.query);
return queryPromise('SOME INSERT QUERY')
.catch(e => {
console.log("It failed", e);
});
}
init().then(result => {
if (result) console.log("It worked", result);
else console.log("Aww, it didn't work");
});

Related

MySQL NodeJS .then() s not a function

Can't I use promise for nodeJS mysql query?
// My DB settings
const db = require('../util/database');
db.query(sqlQuery, [param1, param2])
.then(result => {
console.log(result);
})
.catch(err => {
throw err;
});
It is returning: TypeError: db.query(...).then is not a function
You mentioned in the comments that you want logic after the query block to be awaited, without placing that logic inside of the callback. By wrapping the method with a Promise, you can do that as such:
try {
const result = await new Promise((resolve, reject) => {
db.query(sqlQuery, (error, results, fields) => {
if (error) return reject(error);
return resolve(results);
});
});
//do stuff with result
} catch (err) {
//query threw an error
}
Something like this should work
function runQuery(sqlQuery){
return new Promise(function (resolve, reject) {
db.query(sqlQuery, function(error, results, fields) {
if (error) reject(error);
else resolve(results);
});
});
}
// test
runQuery(sqlQuery)
.then(function(results) {
console.log(results)
})
.catch(function(error) {
throw error;
});
mysql package does not support promise. We can use then only a function call returns a promise.You can use mysql2 which has inbuilt support for Promise. It will also make your code more readable. From mysql2 docs:
async function main() {
// get the client
const mysql = require('mysql2/promise');
// create the connection
const connection = await mysql.createConnection({host:'localhost',
user: 'root', database: 'test'});
// query database
const [rows, fields] = await connection.execute(query);
// rows hold the result
}
I would aslo recommend you to learn about callbacks, promise and async-await

Stop another .then() execution in chain of promises

I have programme in nodejs & mysql like below
db.query()
.then(1)
.then(2)
.then(3)
.catch()
I am checking a value from database in then(1) and trying to return response from there.In then(2) , I am executing another code that uses some data from result of then(1) and so on..
My problem: When returning response from then(1), catch() is calling(because then(2) have error, not getting data from then(1)) . So is there any way I can stop further execution in then(1) so that then(2) and catch() couldn't call ?
db.query('query......', [val1, val2])
.then(rslt => { return res.json({ mssg: "Email already exists!", error: "Email already exists!" }) })
.then(user => { return db.query('INSERT INTO ', value, (err, res, flds) => { err ? reject(err) : resolve(res) }) })
.then(user => { return res.json({ mssg: "Success", success: true}) })
.catch( (err) => { console.log(err) })
You can (and should) use an async function, instead of using the lower-level .then() API of the Promise object:
async function doTheThing() {
try {
const result = await db.query('...');
if (result) { // user exists
return res.json({...}); // this will end the entire function
}
const user = await db.query('...');
return res.json({...}); // success
} catch (err) {
console.log(err); // I don't recommend doing this. try/catch should be for recovery
}
}

NodeJS and SQL with Async

I'm trying to use a SQL query with NodeJs but the async part really mess me up. When i print the return it gets "undefined". How can i sync this?
function SQL_test(blos) {
DB.query("Select profesor_id from materiador where materia_id = '"+blos+"';",function (err, results, fields) {
return results;
});
}
console.log(SQL_test(1));
Thanks!
So your answer is currently a promise. You'll have to read about Async and Await to do more synchronous JS.
Most of the JS for NodeJS is currently async. Below is a rewritten version of your example properly utilizing the callback method for your DB.
function callback (err, results, fields) {
if (err) {
console.log(err);
return err;
}
console.log(results, fields);
return results;
};
function SQL_test(blos) {
DB
.query("Select profesor_id from materiador where materia_id = '"+blos+"';", callback);
}
SQL_test(1);
To do the same thing synchronously you have to still have an outer level promise, otherwise Async and Await won't work how you want it to. There's no true synchronous way to handle this is javascript because it executes without waiting for the response.
function sqlTest(blos) {
return new Promise((resolve, reject) => {
DB.query(
`Select profesor_id from materiador where materia_id = '${blos}';`,
(err, results) => {
if (err) return reject(err)
resolve(results)
}
);
}
)
sqlTest(1)
.then(console.log)
.catch(console.error)

How to do transaction operation for a number of mysql queries in node js using promise?

I have 27 mysql update queries on a single table. All these queries are to be run in a transaction mode, like if one operation fails all other updated queries should rollback.
How I will implement this nodejs with promises?
I'm assuming you use mysql driver found here.
According to documentation, this drivers natively supports transactions like this (copied from documentation):
connection.beginTransaction(function(err) {
if (err) { throw err; }
connection.query('INSERT INTO posts SET title=?', title, function (error, results, fields) {
if (error) {
return connection.rollback(function() {
throw error;
});
}
connection.query('INSERT INTO log SET data=?', log, function (error, results, fields) {
if (error) {
return connection.rollback(function() {
throw error;
});
}
connection.commit(function(err) {
if (err) {
return connection.rollback(function() {
throw err;
});
}
console.log('success!');
});
});
});
});
Since you mentioned promises, you would want to use promise-mysql package which wraps mysql calls in Bluebird promises.
You can use below approach to handle your secnario.
Create an array of queries which needs to be run. In below example I have created queries and their placeholder values and passed them as an array of objects
return a promise to caller which gets resolved when all queries supposed to be run inside a transaction finished
start the transaction
run queries one by one inside transaction block
store the result inside an accumulator as soon as query returns result
if all transactions are complete the commit the transaction and return accumulated result to caller
otherwise rollback the transaction and return the error to caller via promise
Below is the approach which I have mentioned -
function executeTransaction(queries) {
try {
const connection = yield getConnectionObj({/* your db params to get connection */)
let results = []
return new Promise(function(resolve, reject) {
connection.beginTransaction(function (err) {
if (err) throw err
console.log("Starting transaction")
queries
.reduce(function (sequence, queryToRun) {
return sequence.then(function () {
parent.query(queryToRun.query, queryToRun.values)
/* pass your query and connection to a helper function and execute query there */
return queryConnection(
connection,
query,
queryParams,
).then(function (res) {
/* Accumulate resposes of all queries */
results = results.concat(res)
})
}).catch(function (error) {
reject(error)
})
}, Promise.resolve())
.then(function () {
connection.commit(function (err) {
if (err) {
/* rollback in case of any error */
connection.rollback(function () {
throw err
})
}
console.log('Transactions were completed!')
/* release connection */
connection.release()
/* resolve promise with all results */
resolve({ results })
})
})
.catch(function (err) {
console.log('Transaction failed!')
connection.rollback(function () {
console.log('Abort Transaction !!!')
throw err
})
})
})
})
/* End Transaction */
} catch (error) {
return Promise.reject(error)
}
}

javascript promise catch confusion [duplicate]

What is the best way to handle this scenario. I am in a controlled environment and I don't want to crash.
var Promise = require('bluebird');
function getPromise(){
return new Promise(function(done, reject){
setTimeout(function(){
throw new Error("AJAJAJA");
}, 500);
});
}
var p = getPromise();
p.then(function(){
console.log("Yay");
}).error(function(e){
console.log("Rejected",e);
}).catch(Error, function(e){
console.log("Error",e);
}).catch(function(e){
console.log("Unknown", e);
});
When throwing from within the setTimeout we will always get:
$ node bluebird.js
c:\blp\rplus\bbcode\scratchboard\bluebird.js:6
throw new Error("AJAJAJA");
^
Error: AJAJAJA
at null._onTimeout (c:\blp\rplus\bbcode\scratchboard\bluebird.js:6:23)
at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
If the throw occurs before the setTimeout then bluebirds catch will pick it up:
var Promise = require('bluebird');
function getPromise(){
return new Promise(function(done, reject){
throw new Error("Oh no!");
setTimeout(function(){
console.log("hihihihi")
}, 500);
});
}
var p = getPromise();
p.then(function(){
console.log("Yay");
}).error(function(e){
console.log("Rejected",e);
}).catch(Error, function(e){
console.log("Error",e);
}).catch(function(e){
console.log("Unknown", e);
});
Results in:
$ node bluebird.js
Error [Error: Oh no!]
Which is great - but how would one handle a rogue async callback of this nature in node or the browser.
Promises are not domains, they will not catch exceptions from asynchronous callbacks. You just can't do that.
Promises do however catch exceptions that are thrown from within a then / catch / Promise constructor callback. So use
function getPromise(){
return new Promise(function(done, reject){
setTimeout(done, 500);
}).then(function() {
console.log("hihihihi");
throw new Error("Oh no!");
});
}
(or just Promise.delay) to get the desired behaviour. Never throw in custom (non-promise) async callbacks, always reject the surrounding promise. Use try-catch if it really needs to be.
After dealing with the same scenario and needs you are describing, i've discovered zone.js , an amazing javascript library , used in multiple frameworks (Angular is one of them), that allows us to handle those scenarios in a very elegant way.
A Zone is an execution context that persists across async tasks. You can think of it as thread-local storage for JavaScript VMs
Using your example code :
import 'zone.js'
function getPromise(){
return new Promise(function(done, reject){
setTimeout(function(){
throw new Error("AJAJAJA");
}, 500);
});
}
Zone.current
.fork({
name: 'your-zone-name',
onHandleError: function(parent, current, target, error) {
// handle the error
console.log(error.message) // --> 'AJAJAJA'
// and return false to prevent it to be re-thrown
return false
}
})
.runGuarded(async () => {
await getPromise()
})
Thank #Bergi. Now i know promise does not catch error in async callback. Here is my 3 examples i have tested.
Note: After call reject, function will continue running.
Example 1: reject, then throw error in promise constructor callback
Example 2: reject, then throw error in setTimeout async callback
Example 3: reject, then return in setTimeout async callback to avoid crashing
// Caught
// only error 1 is sent
// error 2 is reached but not send reject again
new Promise((resolve, reject) => {
reject("error 1"); // Send reject
console.log("Continue"); // Print
throw new Error("error 2"); // Nothing happen
})
.then(() => {})
.catch(err => {
console.log("Error", err);
});
// Uncaught
// error due to throw new Error() in setTimeout async callback
// solution: return after reject
new Promise((resolve, reject) => {
setTimeout(() => {
reject("error 1"); // Send reject
console.log("Continue"); // Print
throw new Error("error 2"); // Did run and cause Uncaught error
}, 0);
})
.then(data => {})
.catch(err => {
console.log("Error", err);
});
// Caught
// Only error 1 is sent
// error 2 cannot be reached but can cause potential uncaught error if err = null
new Promise((resolve, reject) => {
setTimeout(() => {
const err = "error 1";
if (err) {
reject(err); // Send reject
console.log("Continue"); // Did print
return;
}
throw new Error("error 2"); // Potential Uncaught error if err = null
}, 0);
})
.then(data => {})
.catch(err => {
console.log("Error", err);
});