Catching Uncaught Error in my async await function - node.js

I am trying to use async/await keywords with Redis and NodeJS. I can catch simple errors but I can't catch exceptions coming from getKeys function. Following mocha test fails. My catch block is also not called. I am using NodeJS v9.3.0 and bluebird v3.5.1 and redis 2.8.0
const redis = require("redis");
const bluebird = require("bluebird");
const assert = require('assert');
bluebird.promisifyAll(redis.RedisClient.prototype);
class RedisManager {
constructor(host) {
this.client = redis.createClient({'host':host});
}
async getKeys(key) {
let result = await this.client.hgetallAsync(key);
return result;
}
async simple(key) {
throw Error('Simple Error: ' + key)
}
}
describe('Redis Manager Test:', function() {
it('catches simple errors',function (done) {
let manager = new RedisManager('BOGUSHOST');
let key = 'testKey';
manager.simple(key)
.then(function (value) {
console.log('Value: ' + value);
done(value,null)
})
.catch(function (err) {
if (err = Error('Simple Error: ' + key)) {
done(null);
} else {
done(err);
}
})
});
it('catches Redis errors',function(done) {
let manager = new RedisManager('BOGUSHOST');
manager.getKeys('Some')
.then(function(value) {
console.log('Value: ' + value);
done(value,null)
})
.catch(function (err) {
console.log('Caught Error: ' + err);
done(err,null);
})
})
});

You should use try/catch block to handle Uncaught error rejection when using async/await.
async getKeys(key) {
let result = await this.client.hgetallAsync(key);
try {
return result;
}
catch (err) {
return err;
}
}

Related

Error: DPI-1002: invalid dpiConn handle: Nodejs, Oracledb

I have the following API, the API is inserting into a table based on user selection from the client. User can select different material belonging to same experiment. In my payload, I have materials as array, experiment as string. I tried several ways to resolve my error. Following was the last try:
app.post("/insertMaterials", (req, res) => {
for (let mat of req.body["material"]) {
try {
oracledb.getConnection(
{
user: "some_user",
password: "some_pw",
connectString: "someConnStr",
},
function (err, connection) {
if (err) {
console.error("1" + err);
return;
}
connection.execute(
"INSERT INTO MATERIALS (ID, MAT_NAME, EXPR) VALUES((SELECT max(ID) + 1 FROM MATERIALS), :1, :2)",
[mat, req.body["experiment"]],
(err, result) => {
if (err) {
console.error("log " + err);
}
connection.commit();
connection.close();
}
);
}
);
} catch (error) {
console.log(error);
}
}
return res.status(200).json({
title: "SUCCESS: Materials Inserted",
});
});
I always get:
triggerUncaughtException(err, true / fromPromise /);
^
[Error: DPI-1002: invalid dpiConn handle] { errorNum: 0, offset: 0 }
Before I had a separate function of the block inside the for loop and I also tried with execeuteMany. Still same error. After trying lot other ways and reading in internet, I couldn't solve the issue. Except for finally catching uncaughtException and logging the error:
process.on('uncaughtException', (error, next) => {
let date = new Date()
errorLogStream.write(`Date: ${date}. Err: ${error.stack} \n`)
return
})
By catching this exception, my program does not break anymore and data is always inserted. But it would be great to know how and when this is raised and how this can be resolved or where if I am doing a mistake.
UPDATE
Payload example: {'material': ['F99999.7', 'J84845.4'], 'experiment': 'NA32R'}
Function:
async function addMatToExpr(exp, mat) {
let connection;
try {
connection = await oracledb.getConnection(
{
user: "some_user",
password: "some_pw",
connectString: "someConnStr",
});
result = await connection.execute("INSERT INTO MATERIALS (ID,
MAT_NAME, EXPR) VALUES((SELECT max(ID) + 1 FROM MATERIALS), :1, :2)",
[exp, mat], { autoCommit: true })
} catch (error) {
return res.status(404).json({
title: error,
});
} finally {
if (connection) {
try {
await connection.close()
} catch(error) {
console.log(error)
}
}
}
}
API:
app.post("/insertMaterials", (req, res) => {
for (let mat of req.body["materials"]) {
addMatToExpr(req.body["experiment"], mat)
}
});
Added the async/await function and the api that calls the function.
You need to 'await' the Oracle function calls so each completes before continuing. Currently the connection is being closed before the statement is executed.
See all the node-oracledb documentation and examples.
E.g.
async function run() {
let connection;
try {
connection = await oracledb.getConnection(dbConfig);
result = await connection.execute(sql, binds, options);
console.dir(result, { depth: null });
} catch (err) {
console.error(err);
} finally {
if (connection) {
try {
await connection.close();
} catch (err) {
console.error(err);
}
}
}
}

mongodb method without function not working in nodejs

I don't know much Javascript and was making a nodejs app. My mongodb query in nodejs is working only when the query has a function method like .toArray
Here's the database.js file
const {MongoClient} = require('mongodb');
const uri = "mongodb+srv://name:pass#clusterurl/metro4?retryWrites=true&w=majority";
// all fields are correctly filled
const client = new MongoClient(uri);
try {
// Connect to the MongoDB cluster
client.connect(err =>{
if(err) throw err;
let db = client.db('metro4');
db.collection('Station').find().toArray(function(err, result){
if(err) throw err;
console.log(result);
});
let a = db.collection('Station').findOne({'_id':4});
if(a) {
console.log(a);
}
else{
console.log("No a\n");
}
module.exports = db;
});
} catch (e) {
console.error(e);
} finally {
client.close();
}
when I run the app, the db.collection('Station').find().toArray runs fine and output the result but the second query of findOne doesn't work.
Any help is appreciated.
The findOne method returns a Promise. You should handle its result in a callback function:
db.collection('Station').findOne({ _id: 4 }, function (err, a) {
if (err) {
console.log(err);
} else if (a) {
console.log(a);
} else {
console.log('No a\n');
}
});
Or using async - await:
client.connect(async (err) => {
...
let a = await db.collection('Station').findOne({ _id: 4 })
...
});
EDIT
To handle the import - export problem you should handle the datase connection operations separate async functions.
You may use the connection function to return the database instance:
const {MongoClient} = require('mongodb');
const uri = "mongodb+srv://name:pass#clusterurl/metro4?retryWrites=true&w=majority";
// all fields are correctly filled
const client = new MongoClient(uri);
const connectDB = async () => {
try {
// Connect to the MongoDB cluster
await client.connect();
return client.db('metro4');
} catch (e) {
throw e;
}
}
const disconnectDB = () => {
client.close();
}
module.exports = { connectDB, disconnectDB };
Then use these functions to handle your database related operations:
const { connectDB, disconnectDB } = require('../database');
const getStations = async () => {
const db = connectDB();
if (!db) return;
try {
const data = await db.collection('Station').find().toArray();
return data;
} catch (err) {
throw err;
} finally {
disconnectDB();
}
}
const getStation = async (id) => {
const db = connectDB();
if (!db) return;
try {
const data = await db.collection('Station').findOne({ _id: id});
return data;
} catch (err) {
throw err;
} finally {
disconnectDB();
}
}

Handle UnhandledPromiseRejectionWarning in a function calling another functions

I am having problems do handle UnhandledPromiseRejectionWarning in a function that call other functions making axios request.
const getCode = async () => {
const code = await baseURL.get('/gcs/login/k?codigoCanal=4')
return code
}
const posLogin = async (code) => {
const poslogin = await baseURL.get(`/resource/autenticar/${code}`)
return poslogin
}
const login = async () => {
try {
const code = await getCode();
const finishedLogin = async posLogin(code)
} catch (error) {
handleLoginError(error)
}
}
const handleLoginError = (error) => {
if (error.response.status === 400) {
throw new Error(`Bad Request; ${error.response.statusText}`)
}
if (error.response.status === 401) {
throw new Error(`Wrong credentials; ${error.response.statusText}`)
}
throw new Error('Unknown Error')
}
login()
Executing this code returns me UnhandledPromiseRejectionWarning, but I realized that if I put a try catch inside the catch of login functionn, this warning disappears
} catch (error) {
try {
handleLoginError(error)
} catch (err) {
console.log('Ooppss', err)
}
When I do this my code enter in the nested catch and the "err" value is the value of the handleLoginError(error)
How can I do the same without executing a try catch inside the catch?
It seems you need to call login as follows:
try {
await login();
}
catch(err) {
// handle here the error
}

How to return a promise using web sockets?

I have this function:
function authentification(jsonHeder: any): Promise<boolean> {
return new Promise(function(resolve, reject) {
const ws = new WebSocket('ws://localhost:8000');
if (!jsonHeder.email || !jsonHeder.password) reject(new Error('bad request'));
ws.onopen = async function() {
ws.send(JSON.stringify({
command: '-userLogin',
instanceIdentifier: jsonHeder.email,
password: jsonHeder.password
})
);
};
ws.onmessage = async function(message) {
const json = JSON.parse(message.data.toString());
if (json.isError === false) {
resolve();
} else {
reject(new Error('bad request'));
}
}
});
}
and I'm trying to get the approval for an authentification, and when I am trying to print the result I receive a Promise { }.
the call function is like this:
const result = authentification(jsonHeder);
console.log('result: ', result);
and when I'm trying to put await operator I received a compile error. What can I do?

failed to connect to xxxxx:xxxx in 150000ms node mssql

I have a node js job. This job is using node-cron to run some logic in every hour.
It's connecting to sql server database using node mssql package.
connection file code:
const sql = require('mssql');
const conn = (function () {
try {
return new sql.ConnectionPool(obj);
}
catch (err) {
throw err;
}
}())
const pool = (function () {
try {
return conn.connect();
}
catch (err) {
throw err;
}
}());
const myConn = async function getConn() {
try {
return await pool;
} catch (err) {
throw err;
}
};
module.exports = {
myConn
}
Code to call stored procedure:
async function callProc(procedureName, inputList, callback) {
try {
const pool = await connectionFile.myConn();
const request = new sql.Request(pool);
if (inputList) {
for (const param of inputList) {
request.input(param.name, param.type, param.value);
}
}
const result = await request.execute(procedureName);
callback(null, result);
}
catch (err) {
callback(err, null);
}
}
Intermittently my job is failing with error "failed to connection to in 15000ms"
Any suggestion?

Resources